每次添加新曲目时递增计数器,并且始终 select 尚未分配的最小值 (>=1)

Increment counter each time a new track is added and always select the smallest value (>=1) that is not already assigned

我目前正在做一个火车模拟项目,我有一个列表,其中保存了所有轨道:

    private List<Track> tracks;

    public void addTrack(Track track) {
        this.tracks.add(track);
    }

    public void removeTrack(Track track) {
        if (!tracks.contains(track)) {
            this.tracks.remove(track);
        } else {
            Terminal.printError("track with id " + track.getId() + " doesn't exist.");
        }
    }

我想在添加时为每个曲目分配一个 ID(从 1 开始)。此外,总是选择下一个空闲 ID。例如,如果分配了 ID 1、3、4、5,则使用下一个 ID 2。

E. g.:

添加曲目... -> ID: 1

添加曲目... -> ID: 2

删除曲目 1

添加曲目... -> ID: 1

我会使用地图,每次添加新轨道时,计数器都会加一。但是,如果我删除一个 ID 并添加一个新曲目,将会有 "gaps"。

执行此操作的好方法是什么?

一种方法是在另一个数据结构(可能是 BitSet)中跟踪每个分配的 ID,尤其是 BitSet#nextClearBit(int) 方法

因此,每次将内容放入 List<Tracks> 时,您都会在 BitSet 中设置相对索引,并在删除 Track 时删除。

类似下面的内容

BitSet b = new BitSet();
// set the bits while adding tracks
b.set(0);
b.set(1);
b.set(2);

b.clear(1); // some track gets removed, so unset the bit
System.out.println(b); // {0, 2}

System.out.println(b.nextClearBit(0)); // 1

就像 Saif Asif 在他的回答中提到的那样,您可以使用另一种数据结构来跟踪 ID。

BitSet 是一种方法,另一种方法是使用 TreeSet 跟踪您分配和撤销的 ID,这将为您保持 ID 的顺序

例如

public class IdTracker {

    private TreeSet<Long> available;
    private TreeSet<Long> current;

    public IdTracker() {
        this.available = new TreeSet<Long>();
        this.current = new TreeSet<Long>();
    }

    public long getNextId() {
        //Check to see if this is the first time being called, setting initial id to 1
        if (available.isEmpty() && current.isEmpty()) {
            current.add(1L);
            return 1L;
        }

        //Check to see if we have any available values to use
        if (!available.isEmpty()) {
            //Remove from available and assign to current
            Long availableId = available.first();
            available.remove(availableId);
            current.add(availableId);
            return availableId;
        }

        //There are no available id's, get the highest current id and increment
        Long highestCurrentId = current.last();
        Long nextId = highestCurrentId + 1;
        current.add(nextId);
        return nextId;
    }

    public void removeId(long id) {
        //Remove from the current (if there) and place into available
        if (current.remove(id)) {
            available.add(id);
        } else {
            //Handle your failure case
        }
    }
}

所以在你的例子中你会做

private List<Track> tracks;
private IdTracker idTracker;

public void addTrack(Track track) {
    long id = idTracker.getNextId();
    track.setId(id);
    this.tracks.add(track);
}

public void removeTrack(Track track) {
    if (tracks.contains(track)) {
        this.tracks.remove(track);
        this.idTracker.removeId(track.getId());
    } else {
        Terminal.printError("track with id " + track.getId() + " doesn't exist.");
        }
    }