Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在附加值上返回索引的ArrayList_Java_Data Structures_Collections - Fatal编程技术网

Java 在附加值上返回索引的ArrayList

Java 在附加值上返回索引的ArrayList,java,data-structures,collections,Java,Data Structures,Collections,我正在寻找一种类似于ArrayList的java数据结构,当我只使用一个值参数进行添加或推送时,会自动为我返回一个索引 例如: ArrayList<String> elements = new ArrayList<String>(); String element = "foo"; String elementTwo = "bar"; int index1 = elements.add(element); //note this does not exist, i.e

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

例如:

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周围编写一个包装器吗?这似乎很简单,可以在某个地方开箱即用

编辑:


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

元素将添加到列表的末尾。因此,您可以使用
elements.size()-1
获取新元素索引

请注意,如果多个线程同时修改列表,这将无法可靠地工作

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

  • 确保从不从列表中删除元素,也从不使用
    add(int,Object)
    添加元素
  • 除了删除元素,您还可以使用方法
    set(int,null)
    将它们设置为
    null
    。这样,任何元素索引都不会更改
  • 使用其他一些数据结构,例如一个带有自定义ID的地图,如helloannalil在其答案中建议的那样
编辑2:我没有找到合适的、随时可用的实现(当然,这并不意味着没有)。为了提出一个好的解决方案,需要更多关于数据结构预期用途的信息,但这里有一些想法和注意事项:

  • 如果元素的最大数量不太大,可以使用
    ArrayList
    ,元素索引表示ID。如上所述,要删除元素,可以将其设置为
    null
    ,以便不更改索引。插入时,可以重用具有
    null
    值的位置
  • 您还可以使用此答案中显示的两种方法之一:(关键字
    AtomicLong
    IdentityHashMap
  • 不要依赖于
    Object.hashCode()
    System.identityHashCode(Object)
    的“唯一性”,因为这是不可靠的(请运行本部分底部的示例进行尝试)

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

String thing = "theThing";
List<String> strList = new ArrayList<String>();
strList.add(thing);
int indexOfThing = strList.size() - 1;
String thing=“theThing”;
List strList=new ArrayList();
添加(事物);
int indexOfThing=strList.size()-1;

我的意思是,这比实现自己的列表更容易,而且很有效

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

基于你的评论和编辑的问题,我想你可以像这样扩展一个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;
    }
}
private MyMap<String> map = new MyMap<String>();
.....
.....
String element = "foo";
String elementTwo = "bar";
int index1 = map.add(element);
int index2 = map.add(elementTwo);
String elem1 = map.get(index1); // will return "foo"
String elem2 = map.get(index2); // will return "bar"
然后将元素添加到
MyMap
,如下所示:

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;
    }
}
private MyMap<String> map = new MyMap<String>();
.....
.....
String element = "foo";
String elementTwo = "bar";
int index1 = map.add(element);
int index2 = map.add(elementTwo);
String elem1 = map.get(index1); // will return "foo"
String elem2 = map.get(index2); // will return "bar"
现在您有了
index1
index2
作为插入字符串的索引,可以在应用程序的生命周期中使用或传递这些字符串。您可以在
MyMap
中插入或删除任意次数的元素,但索引(
index1
index2
)将返回插入的元素,如下所示:

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;
    }
}
private MyMap<String> map = new MyMap<String>();
.....
.....
String element = "foo";
String elementTwo = "bar";
int index1 = map.add(element);
int index2 = map.add(elementTwo);
String elem1 = map.get(index1); // will return "foo"
String elem2 = map.get(index2); // will return "bar"
String thing=“theThing”;
List strList=new ArrayList();
添加(事物);
int indexOfThing=strList.size()-1;

如果删除项目,则此操作将不再有效。

int index1=elements.add(element).size()-1
;这不管用吗
int index1=elements.size()有什么问题;元素。添加(元素)?我很困惑。为什么写第二行来获取当前长度会如此糟糕???如果使用该大小,是否总是保证获得唯一的ID?如果在添加之间删除一个元素会发生什么?@RyanR。我更新了我的答案以涵盖这个问题。谢谢你的答案(+1)。我们将检查一个答案,其中包含有关map实现或缺少map实现的更多详细信息。@RyanR。我添加了一些实现想法和注释…我喜欢这项研究。我主持了HashClash课程。有趣的是,在那里看到了独特性的突破。我的系统中没有100亿次试验,但很高兴知道。尽管@anubhava也有一些很好的输入,我还是会给你检查一下(由于背景研究)。@RyanR。谢谢:-)我知道这种独特性不能保证,但我不知道打破它有多“容易”…是的,他有一些优点。没有他我可能不会做这项研究,所以也谢谢你,阿努巴瓦;-)回答得不错(+1),这属于我问题的“实现我自己的包装器”部分。如果没有其他人能想出一个更“标准库”的方法,我会在支票上拖延一段时间,但最终会给你。好奇这是否是实现这一点的最明智的方式?如果您知道有一组有界的元素,那么最好围绕一个固定大小的数组编写这类内容?是的,这属于您问题的
实现我自己的包装器部分。IMO使用任何基于数组或集合的实现都需要更多的代码,因为您将从该存储中添加/删除元素。@RyanR。请注意,根据的Javadocs,这并不能保证有效,JVM不需要为不同的obj返回不同的哈希代码