Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What data structure should I use for object storage, for easily generating primary keys for new entries?

Tags:

java

I'm doing a school project in Java and I the following question have arisen:

I have an entity with attributes - id, name, phone.. with id as the unique primary key. I want to store them in a data structure(such as list..). Then in the application I obtain the data for creating a new instance (name, phone..) and I want to create a new instance of the entity and store it in my data structure with a new unique id. The id shouldn't be random, it would be best if the id rised continuously with the size of the list. Also I dont want to reuse ids.

The first implementation that comes to my mind is to use ArrayList and simply set id as indexes. But ArrayList.remove(int index) after removal shifts all following elements to left. I assume that ArrayList.remove(Object o) works the same, but i would be gratefull i I'm proven wrong. Determining ids from last element would not work either. I could go through all of them but that seems inefiicient.

Thanks in advance for any help :)

like image 733
Ondrej Sotolar Avatar asked Sep 14 '25 02:09

Ondrej Sotolar


2 Answers

You want to keep a counter for them. You could use a static value in the class (you may need to synchronize it for multi-threaded classes.)

import java.util.concurrent.atomic.AtomicInteger;
class MyClass {


    // thread safe
    private static final AtomicInteger safeCounter = new AtomicInteger();

    private final int uniqueId; // can never change uniqueId
    private String name; // the data of the class

    public MyClass(String name) {
        this.name = name;
        this.uniqueId = MyClass.safeCounter.getAndIncrement();
    } 

    public boolean equals(Object o) {
        if(o instanceof MyClass) { // instanceof also does null check :-)
            MyClass mc = (MyClass)o;
            return mc.uniqueId == this.uniqueId;
        }
        return false;
    }

    public int hashCode() {
        return uniqueId;
    }
}

If this is for homework, or if threadsafety isn't a concern, you can use a simple static int

class MyClass {

    private static int nextUniqueId() {
        int result = counter;
        counter++;
        return result;
    }

    // not thread safe
    private static int counter;

    private final int uniqueId; // can never change uniqueId
    private String name; // the data of the class

    public MyClass(String name) {
        this.name = name;
        this.uniqueId = nextUniqueId();
    } 

    public boolean equals(Object o) {
        if(o instanceof MyClass) { // instanceof also does null check :-)
            MyClass mc = (MyClass)o;
            return mc.uniqueId == this.uniqueId;
        }
        return false;
    }

    public int hashCode() {
        return uniqueId;
    }
}
like image 199
corsiKa Avatar answered Sep 15 '25 16:09

corsiKa


How about using a Factory that users a Strategy for generating your identifiers?

Edited to answer question about factories

A Factory is a design pattern that is used to encapsulate the creation of different types of Objects. A Strategy is another design pattern that is used to encapsulate the behavior of specific business logic that might have different rules or that might change over time.

In your case you clearly require a new Identifier for each object that needs to be unique. You also stated in your question comments above that eventually you will be storing your objects in a database, which also would most likely require you to get your identifier from your database in the long run.

Here is a smallish example of using a Factory to create your User Objects instead of just using new(). Please kindly disregard any spelling or compile mistakes, I wrote the following code with out the assistance of a compiler or IDE.

public interface UserFactory {
    User createUser();
}

public interface IdentifierStrategy {
    // I just picked Long for ease of use.
    Long getIdentifier();
}

public class UserFactoryImpl {
    private final IdentifierStrategy identifierStrategy;
    public UserFactoryImpl(final IdentifierStrategy identifierStrategy) {
        this.identifierStrategy = identifierStrategy;
    }
    public User createUser() {
        Long identifier = this.identifierStrategy.getIdentifier();
        User user = new User(identifier);
        return user;
    }
}

public class LongIdentifierStrategy implements IdentifierStrategy {
    public Long getIdentifier() {
        // Do something here that will return a unique long.
        Long long = new Long(1);
        return long;
    }
}

// In the long term, you would most likely use this IdentiferStrategy
// to get your identifiers from the database.
public class JDBCIdentifierStrategy implements IdentifierStrategy {
    public Long getIdentifer() {
        // Get a jdbc connection from a jdbc connection pool.
        // Get the next identifier from the databsae.
        Long long = new Long(1);
        return long;
    }
}

Now, in the long run, if your requirement change for how you need to identifier your User objects, you would only need to write a new IdentifierStrategy and update your UserFactoryImpl with that new Strategy.

like image 36
hooknc Avatar answered Sep 15 '25 14:09

hooknc