11

我正在寻找一个类似于 ArrayList 的 java 数据结构,当我只使用 value 参数进行添加或推送时,将自动为我返回索引。

例如:

ArrayList<String> elements = new ArrayList<String>();

String element = "foo";
String elementTwo = "bar";

int index1 = elements.add(element); //note this does not exist, i.e. returns bool in api
int index2 = elements.add(elementTwo);

System.out.println(elements.get(index1)); //would give "foo"

我可以看到围绕 ArrayList 编写一个包装类,该类管理一个计数器,该计数器在每次添加操作和调用时递增:

ArrayList.add(int index, E element)

你真的需要为此写一个 ArrayList 的包装器吗?这似乎很简单,可以在某个地方开箱即用?

编辑:

对于这个用例,我需要固定和唯一的索引(键)。有人建议了一张地图,我同意这一点。有谁知道在值插入时为您提供自动(唯一)生成的键的映射实现?我只是想决定是否需要为此实现自己的包装器。

4

5 回答 5

7

该元素将被添加到列表的末尾。所以你可以使用elements.size()-1来获取新的元素索引。

请注意,如果多个线程同时修改列表,这将不可靠。

编辑:还请注意,使用 s 索引作为唯一 ID 可能不是一个好主意,ArrayList因为元素索引可能会更改(例如,当您删除元素或使用 插入新元素时add(int, Object))。如果这是一个问题,取决于您要对索引做什么:如果您在添加元素后只需要它很短的时间,并且可以确保在此期间列表没有被修改,那么没有问题。在另一种情况下,即使在调用时返回索引的方法add(Object)也无济于事,因为无论如何索引都不会更新。为防止出现此问题,您可以:

  • 确保您永远不会从列表中删除元素,也永远不会使用add(int, Object).
  • 除了删除元素,您还可以将它们设置为null使用方法set(int, null)。这样,任何元素索引都不会改变。
  • 使用其他一些数据结构,例如具有自定义 ID 的地图,如 helloannanil 在他的回答中建议。

编辑 2:我没有找到合适的、可立即使用的实现(但这并不意味着没有,当然)。为了提出一个好的解决方案,需要更多关于数据结构预期用途的信息,但这里有一些想法和注意事项:

  • 如果元素的最大数量不是很大,ArrayList可以使用 an 并且元素索引表示 ID。如上所述,要删除一个元素,可以将其设置为null不更改索引。插入时,null可以重复使用具有值的位置。
  • 您还可以使用此答案中显示的两种方法之一:https ://stackoverflow.com/a/8939049/1347968 (关键字AtomicLongIdentityHashMap
  • 不要依赖或因为它不能保证的“唯一性”(通过运行Suns/Oracles Bug #6321873底部的示例来尝试)。Object.hashCode()System.identityHashCode(Object)
于 2012-04-25T03:44:02.877 回答
2

那么在这种情况下我所做的(我喜欢 ArrayLists)是通过询问列表的大小来获取最后一个索引:

String thing = "theThing";
List<String> strList = new ArrayList<String>();
strList.add(thing);
int indexOfThing = strList.size() - 1;

我的意思是,比实现自己的 List 更容易并且可以正常工作。

于 2012-04-25T03:44:32.270 回答
2

如果你真的想要这个功能,你可以使用map而不是list

于 2012-04-25T03:48:25.080 回答
2

根据您的评论和编辑的问题,我认为您可以扩展 HashMap 供您使用,如下所示:

public class MyMap<V> extends HashMap<Integer, V> {
    private static final long serialVersionUID = 1L;
    public int add(V elem) {
        int key = System.identityHashCode(elem);
        super.put(key, elem);
        return key;
    }
}

然后在你的类中声明MyMap如下:

private MyMap<String> map = new MyMap<String>();

然后添加你的元素,MyMap如下所示:

.....
.....
String element = "foo";
String elementTwo = "bar";
int index1 = map.add(element);
int index2 = map.add(elementTwo);

现在,您拥有index1index2作为插入字符串的索引,您可以在应用程序的生命周期内使用或传递这些字符串。MyMap您可以根据需要多次插入或删除元素,但您的索引 (index1index2) 将返回您插入的元素,如下所示:

String elem1 = map.get(index1); // will return "foo"
String elem2 = map.get(index2); // will return "bar"
于 2012-04-25T20:30:33.793 回答
0
String thing = "theThing";
List<String> strList = new ArrayList<String>();
strList.add(thing);
int indexOfThing = strList.size() - 1;

如果您删除一个项目,这将不再有效。

于 2014-09-20T07:29:02.947 回答