簡體   English   中英

在Java中用於此問題的最佳數據結構是什么?

[英]What's a good data structure to use for this issue in Java?

所以我有以下問題:

我想要某種類型的數據存儲,用於存儲一種類型的太空飛船(太空飛船ID)。 每個太空飛船都有一個名字。

情況1

特定類型的太空飛船只能在數據存儲中存儲一次。 因此,如果用戶嘗試存儲以下內容,則名稱1:太空飛船類型1和名稱2:太空飛船類型1將僅在數據結構中存儲1個太空飛船類型1實例。

情況二

如果用戶輸入名稱1:太空飛船類型1,然后輸入名稱1:太空飛船類型2,則數據結構應僅存儲名稱1:太空飛船類型2。這意味着太空飛船類型1已由太空飛船類型2替換,因為它們具有一樣的名字。


解決此問題的最初方法是使用哈希圖,我將對飛船ID進行哈希處理,因此,如果兩個飛船ID相同,則在哈希圖中僅將飛船ID存儲一次,作為值,我將得到一個數組映射到相同太空飛船ID的名稱。 解決了情況1。

情況2更成問題。 哈希圖可能會很大,我認為遍歷每個存儲桶中的每個數組以識別是否已使用名稱來從哈希圖中刪除該名稱以及可能的太空飛船ID並添加條目的效率很低以及新的太空飛船ID及其對應的名稱。

在這種情況下,最好使用哈希圖,還是可以使用另一種數據結構來解決這兩種情況。 也許我必須自己創造一個。 正確方向的任何指針都將有所幫助。

最好使用單獨的地圖,但是如果您決定繞開任何第三方庫( 除非我打算不同意這個決定,除非其目的是學習如何創建自己的Map ),否則想到它的最簡單方法是如果你有兩張Maps

Map<String, String> typeToName; //if you could have multiple of the Value, it could be Set<String>
Map<String, String> nameToType;

//put "Type1", "DoubleDouble's Destroyer" in typeToName
//put "DoubleDouble's Destroyer", "Type1" in nameToType

如果你要添加一個"Type1", "DistractionBoat" ,你會先看看是否有任何"Type1"typeToName ,並從刪除相應的名稱nameToType

然后進行相反的操作,檢查nameToType是否存在"DistractionBoat" ,並從typeToName刪除任何對應的type

然后添加新的太空飛船,它將替換具有相同type name所有太空飛船。

在此基礎上可能可以進行很多改進( 最明顯的是使它更通用並擁有自己的類 )。 實際上,您為了速度而犧牲了內存。

您可以使用兩個映射來實現自己的類,如下所示:

public final class Spaceship {
    private final int    id;
    private final String name;
    public Spaceship(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return this.id;
    }
    public String getName() {
        return this.name;
    }
    @Override
    public String toString() {
        return this.id + ":" + this.name;
    }
}

public final class Spacedock {
    private Map<Integer, Spaceship> byId   = new HashMap<>();
    private Map<String, Spaceship>  byName = new TreeMap<>(); // so getSpaceships() lists ordered by name
    public boolean containsSpaceship(Spaceship spaceship) {
        Spaceship shipInDock = this.byId.get(spaceship.getId());
        return (shipInDock != null && shipInDock.getName().equals(spaceship.getName()));
    }
    public void addSpaceship(Spaceship spaceship) {
        if (! containsSpaceship(spaceship)) {
            Spaceship prevShip = this.byId.put(spaceship.getId(), spaceship);
            if (prevShip != null)
                this.byName.remove(prevShip.getName());
            prevShip = this.byName.put(spaceship.getName(), spaceship);
            if (prevShip != null)
                this.byId.remove(prevShip.getId());
        }
    }
    public void removeSpaceship(Spaceship spaceship) {
        if (containsSpaceship(spaceship)) {
            this.byId.remove(spaceship.getId());
            this.byName.remove(spaceship.getName());
        }
    }
    public Collection<Spaceship> getSpaceships() {
        return this.byName.values();
    }
    public Spaceship getById(int id) {
        return this.byId.get(id);
    }
    public Spaceship getName(String name) {
        return this.byName.get(name);
    }
    @Override
    public String toString() {
        return this.byName.values().toString();
    }
}

測試

Spacedock spacedock = new Spacedock();
spacedock.addSpaceship(new Spaceship(1, "Name1"));
System.out.println(spacedock);
spacedock.addSpaceship(new Spaceship(2, "Name2"));
System.out.println(spacedock);
spacedock.addSpaceship(new Spaceship(1, "Name2"));
System.out.println(spacedock);
spacedock.addSpaceship(new Spaceship(2, "Name2"));
System.out.println(spacedock);
spacedock.addSpaceship(new Spaceship(2, "Name1"));
System.out.println(spacedock);

輸出量

[1:Name1]
[1:Name1, 2:Name2]
[1:Name2]
[2:Name2]
[2:Name1]

如您所見,通過添加具有現有ID或名稱的新飛船將存儲不同的飛船,這將刪除現有飛船。


如果您使用的是Java 8,並且不喜歡空值,請使用新的Optional

public Optional<Spaceship> getById(int id) {
    return Optional.ofNullable(this.byId.get(id));
}
public Optional<Spaceship> getName(String name) {
    return Optional.ofNullable(this.byName.get(name));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM