我有一个名为info
的LinkedHashMap
,它包含名字/年龄(字符串/整数)对。如果我输入键,如何获取该键/值的位置?例如,如果我的LinkedHashMap
如下所示:{bob=12, jeremy=42, carly=21}
,并且我要搜索jeremy
,它应该返回1
,因为它在第一个位置。我希望我可以使用类似于info.getIndex("jeremy")
这样的东西。
我有一个名为info
的LinkedHashMap
,它包含名字/年龄(字符串/整数)对。如果我输入键,如何获取该键/值的位置?例如,如果我的LinkedHashMap
如下所示:{bob=12, jeremy=42, carly=21}
,并且我要搜索jeremy
,它应该返回1
,因为它在第一个位置。我希望我可以使用类似于info.getIndex("jeremy")
这样的东西。
HashMap
的实现通常是无序的,不适合进行 Iteration
。
LinkedHashMap
是可预测的有序的,适合进行 Iteration
(插入顺序),但它不公开 List
接口,而且 LinkedList
(它反映了键集的插入顺序)也不会跟踪索引位置,因此查找索引非常低效。 LinkedHashMap
也不公开内部 LinkedList
的引用。
实际的“链表”行为是特定于实现的。有些可能实际上使用
LinkedList
的实例,有些可能只是让Entry
跟踪前一个和后一个Entry
并将其用作实现。在查看源代码之前不要做任何假设。
包含键的 KeySet
也不能保证顺序,因为继承的 HashMap
在放置时使用哈希算法,所以你不能使用它。
唯一的方法是遍历使用镜像LinkedList
的Iterator
,并保持计数器记录位置,但这对于大数据集非常低效。
解决方案
听起来你想要的是原始插入顺序索引位置,你需要在KeySet
中镜像键到类似ArrayList
的东西中,与HashMap
的更新同步,并用它来查找位置。创建一个HashMap
的子类,比如IndexedHashMap
,在内部添加这个ArrayList
,并添加一个.getKeyIndex(<K> key)
,委托给内部的ArrayList
.indexOf()
可能是最好的方法。
这就是LinkedHashMap
所做的,但是使用镜像LinkedList
代替ArrayList
来镜像KeySet
。
HashSet
的 顺序 可能会在每次插入或删除时发生变化,这并不是有保证的,所以我是正确的,你不能使用它! - user177800int pos = new ArrayList<String>(info.keySet()).indexOf("jeremy")
LinkedHashMap
的 keySet()
方法返回键的顺序是有保证的。参考链接:https://dev59.com/YXA85IYBdhLWcg3wJf8Z. - ykaganovich我在这个问题的一个重复问题中看到了一个建议,链接如下:
我喜欢评论中@schippi所描述的伪代码建议。我认为一些可用的Java代码可能对其他人有用。
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class IndexedLinkedHashMap<K,V> extends LinkedHashMap<K,V> {
/**
*
*/
private static final long serialVersionUID = 1L;
ArrayList<K> al_Index = new ArrayList<K>();
@Override
public V put(K key,V val) {
if (!super.containsKey(key)) al_Index.add(key);
V returnValue = super.put(key,val);
return returnValue;
}
public V getValueAtIndex(int i){
return (V) super.get(al_Index.get(i));
}
public K getKeyAtIndex(int i) {
return (K) al_Index.get(i);
}
public int getIndexOf(K key) {
return al_Index.indexOf(key);
}
}
List<String> keys = List.copyOf( yourLinkedHashMap.keySet() );
System.out.println( keys.indexOf("jeremy") ); // prints '1'
com.google.common.collect.LinkedListMultimap
。你不需要这个类的多重映射行为,你想要的是keys()
方法保证以插入顺序返回它们,然后可以用来构造一个List,你可以使用indexOf()
来找到所需的索引位置。LinkedHashMap
的Iterator
,就无法实现这一点。无论是keyset还是entryset都不能单独提供他们所要求的内容。 - user177800 final int[] index = {0};
Stream<ComplexObject> t = someListOfComplexObject.stream();
ConcurrentMap<String, List<Integer>> m =
t.collect(Collectors.groupingBy(
e -> e.getComplexStringKeyElem(),
Collectors.mapping(
e -> index[0]++,
Collectors.toList()
),
ConcurrentSkipListMap::new));