是否保证java.util.Map
的标准实现中的键和值以相同的顺序返回?例如,如果map包含映射x1 -> y1
和x2 -> y2
,那么如果keySet()
迭代产生x1, x2
,是否保证values()
迭代将产生y1, y2
而不是y2, y1
?我没有看到任何保证这是真的,但它似乎工作。任何人都可以确认或否认这个前提并给出反例吗?
public class MapsTest {
@Test
public void hashMapKeysAndValuesAreInSameOrder() {
assertKeysAndValuesAreInSameOrder(new HashMap<>());
}
@Test
public void treeMapKeysAndValuesAreInSameOrder() {
assertKeysAndValuesAreInSameOrder(new TreeMap<>());
}
private void assertKeysAndValuesAreInSameOrder(Map<Integer, Integer> map) {
Random random = new Random();
IntStream.range(0, 100000).map(i -> random.nextInt()).forEach(i -> map.put(i, i));
assertEquals(new ArrayList<>(map.keySet()), new ArrayList<>(map.values()));
}
}
答案 0 :(得分:3)
来自HashMap docs:
此课程不保证地图的顺序;特别是,它不保证订单会随着时间的推移保持不变。
答案 1 :(得分:3)
来自HashMap
的文件,
此课程不保证地图的顺序;特别是,它不保证订单会随着时间的推移保持不变。
如果您查看其code,您会发现在致电put()
后,最终会计算hash
,entry object
已创建并添加到bucket array
1}}。我简化了代码的目的只是为了解释场景背后发生的事情。
如果您需要保证订单,请根据您的要求使用LinkedHashMap
或TreeMap
同时检查,
答案 2 :(得分:2)
查看http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java#HashMap.values%28%29,我猜它是有效的,因为KeyIterator和ValueIterator都扩展了HashIterator。
但是,只有当你不同时改变HashMap时才会这样做,例如在调用keySet()和values()之间添加和删除项目,因为这可以更改桶大小,并且HashIterator的行为会有所不同。
答案 3 :(得分:1)
有趣的问题。我试了一下。似乎键的RELATIVE排序与值保持同步。
import java.util.*;
public class MapClass {
public static Map<String, Integer> map = new HashMap<>();
public static void main (String[] args){
map.put("first", 1);
map.put("second", 2);
map.put("third", 3);
map.put("fourth", 4);
map.put("fifth", 5);
System.out.println(map.keySet());
System.out.println(map.values());
map.put("sixth", 6);
System.out.println(map.keySet());
System.out.println(map.values());
map.remove("first");
System.out.println(map.keySet());
System.out.println(map.values());
}
}
我明白了:
[third, fifth, fourth, first, second]
[3, 5, 4, 1, 2]
[sixth, third, fifth, fourth, first, second]
[6, 3, 5, 4, 1, 2]
[sixth, third, fifth, fourth, second]
[6, 3, 5, 4, 2]
这个简单的例子似乎表明虽然HashMap
不会保留插入顺序,但它似乎确实保留了键和值的相对顺序。
keyset()和values()不保证任何顺序,但似乎in practice它会为多次调用返回相同的顺序。正如那里的评论所说,即使你可以依赖它,你是否应该这是值得怀疑的。