Java `ArrayList of HashMap` 或 `LinkedHashMap` 按索引获取项目
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18188739/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
`ArrayList of HashMap` or `LinkedHashMap` to get item by index
提问by Vinay W
My need to store a a huge amount of data in the key-value form. Also, I have two requirements
我需要以键值形式存储大量数据。另外,我有两个要求
- query data via the index, like from an array.
- hence the order in the data structure must be preserved.
- 通过索引查询数据,就像从数组中查询。
- 因此必须保留数据结构中的顺序。
For Requirement 2 - I can use a LinkedHashMap.
对于要求 2 - 我可以使用LinkedHashMap。
For Requirement 1 - I have two options :
对于要求 1 - 我有两个选择:
- 1.1 | To implement an ArrayList Of HashMap. [
ArrayList<HashMap<String,String>>
] - 1.2 | To implement a LinkedHashMapand query the items by index using something like
- ->
new ArrayList(hashMapObject.entrySet()).get(0);
- ->
- 1.1 | 实现一个 ArrayList 的 HashMap。[
ArrayList<HashMap<String,String>>
] - 1.2 | 实现LinkedHashMap并使用类似的方法按索引查询项目
- ->
new ArrayList(hashMapObject.entrySet()).get(0);
- ->
The Question is which is better among 1.1
or 1.2
?
现在的问题是这是间好1.1
还是1.2
?
By better, I mean - efficient in terms of memory and space.
更好,我的意思是 -在内存和空间方面高效。
Let's assume the volume of data is in the order of 50 to 100 key-value pairs with average sized Strings - say every key is 10-30 characters and value is 30-50 characters.
让我们假设数据量约为 50 到 100 个键值对,字符串大小平均 - 假设每个键是 10-30 个字符,值是 30-50 个字符。
采纳答案by Vinay W
I went with experimentating it myself. Turns out the method of creating an ArrayList of HashMapsis about 40 times faster with 1000 elements.
我自己去试验了。事实证明,使用 1000 个元素创建HashMap的ArrayList 的方法大约快 40 倍。
public class HashMapVsArrayOfHashMap {
public static void main(String[] args){
ArrayList<HashMap<String, String>> listOfMaps=new ArrayList<HashMap<String,String>>();
for( int i=0;i<1000;i++){
final int finalI=i;
listOfMaps.add(new HashMap<String, String>(){{put("asdfasdfasdfasdfadsf"+finalI,"asdfsdafasdfsadfasdf"+finalI);}});
}
LinkedHashMap<String, String> map=new LinkedHashMap<String, String>();
for(int i=0;i<1000;i++)
map.put("asdfasdfasdfasdfadsf"+i,"asdfsdafasdfsadfasdf"+i);
int position=700;
testArrayList("Method1:ArrayListOfHashMaps",position,listOfMaps);
testHashMap("Method2:LinkedHashMap",position,map);
}
private static void testArrayList(String string, int position,
ArrayList<HashMap<String, String>> listOfMaps) {
long start, end;
start=System.nanoTime();
listOfMaps.get(position).get("asdfasdfasdfasdfadsf"+position);
end=System.nanoTime();
System.out.println(string+"|Difference = "+(end-start));
}
private static void testHashMap(String string, int position,
LinkedHashMap<String, String> map) {
long start, end;
start=System.nanoTime();
String s= new ArrayList<String>(map.keySet()).get(position);
end=System.nanoTime();
System.out.println(string+"|Difference = "+(end-start));
}
}
When you increase the size to 30,000 elements - the difference is HUGE.
当您将大小增加到 30,000 个元素时 - 差异是巨大的。
回答by Kenny Cason
Try using SortedMap.
尝试使用 SortedMap。
For example:
例如:
SortedMap<Key, Value> map = new TreeMap<Key, Value>();
This way you get the fast lookup time (via key), but they also remain ordered.
通过这种方式,您可以获得快速查找时间(通过键),但它们也保持有序。
You can then iterate over the data like so:
然后,您可以像这样迭代数据:
for(Key k : map.keySet()) {
process(map.get(k));
}
I used them recently to analyze 10s millions tweets where the key was a date, and the value was a counter. I wanted to maintain the ordering of the dates.
我最近使用它们分析了数百万条推文,其中键是日期,值是计数器。我想保持日期的顺序。
updateIf you can get by with just itereating over the data, then my method will suffice. Perhaps you could supply a small example? If it's absolutely required that you can reference the data by index as well, it seems like you would just want to maintain two datastructures like @Jim mentioned. I'ved had to do that before.
更新如果您可以通过迭代数据来解决问题,那么我的方法就足够了。也许你可以提供一个小例子?如果绝对需要您也可以通过索引引用数据,那么您似乎只想维护@Jim 提到的两个数据结构。我以前不得不这样做。
回答by Fortega
I think the LinkedHashMap is the best solution, but to get the item, you can use
我认为 LinkedHashMap 是最好的解决方案,但要获得该项目,您可以使用
hashMapObject.values().toArray()[index]
However, the toArray method will be slow for large amounts of data. But that is something you'll have to test.
但是,对于大量数据, toArray 方法会很慢。但这是你必须测试的东西。
If speed is really an issue, you can maintain a HashMap andan ArrayList.
如果速度确实是一个问题,您可以维护一个 HashMap和一个 ArrayList。
回答by Jim Garrison
Remember that collections do not contain the objects, only referencesto objects.
请记住,集合不包含对象,只包含对对象的引用。
Use twocollections:
使用两个集合:
- An
ArrayList
to store the references for access by index - A
HashMap
to store the references for access by key
- An
ArrayList
存储用于按索引访问的引用 - A
HashMap
存储用于按键访问的引用
For example:
例如:
List<MyValue> list = new ArrayList<MyValue>(100000);
Map<MyKey,MyValue> map = new HashMap<MyKey,MyValue>(100000);
while(moreItems) {
// read input
MyKey key = ...
MyValue value = ...
list.add(value);
map.put(key,value);
}
// lookup by index
MyValue v1 = list.get(11241);
// lookup by key
MyValue v2 = map.get(someKey);
If you need to cross-reference (i.e. given a value object, find its index or its key) you have some options:
如果你需要交叉引用(即给定一个值对象,找到它的索引或它的键)你有一些选择:
- Save the index and key in the the value object itself
- Wrap the value in a "handle" that contains the key and index.
- 将索引和键保存在值对象本身中
- 将值包装在包含键和索引的“句柄”中。
For example
例如
class Wrapper {
MyKey key;
MyValue value;
int index;
// constructor, getters and setters
}
int index=0;
while(moreItems) {
// read input
MyKey key = ...
MyValue value = ...
Wrapper w = new Wrapper(key,value,index++);
list.add(w);
map.put(key,w);
}
...
Wrapper w = list.get(23410);
MyKey k = w.getKey();
MyValue v = w.getValue();
int i = w.getIndex();
...