kar*_*rts 71 java iteration hashmap hashset
我知道从Map的keySet()方法返回的Set不保证任何特定的顺序.
我的问题是,它是否保证多次迭代的相同顺序.例如
Map<K,V> map = getMap();
for( K k : map.keySet() )
{
}
...
for( K k : map.keySet() )
{
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,假设映射不修改,将迭代在按键组处于相同的顺序.使用Sun的jdk15它会以相同的顺序迭代,但在我依赖于这种行为之前,我想知道所有JDK是否都会这样做.
编辑
我从答案中看到我不能依赖它.太糟糕了.我希望不必为了保证我的订购而建立一些新的收藏品.我的代码需要迭代,执行一些逻辑,然后使用相同的顺序再次迭代.我将从keySet创建一个新的ArrayList,这将保证顺序.
cia*_*mej 49
如果需要迭代顺序不变的HashMap,可以使用LinkedHashMap.
此外,如果您遍历集合,则应始终使用它.迭代HashMap的entrySet或keySet比使用LinkedHashMap慢得多.
Ken*_*Liu 47
如果API文档中没有说明保证,那么您不应该依赖它.甚至从同一供应商的JDK,行为甚至可能从JDK的一个版本更改为下一个版本.
您可以轻松获得该设置,然后自己对其进行排序,对吧?
Map只是一个接口(而不是一个类),这意味着实现它的底层类(并且有许多)可能表现不同,API中keySet()的契约并不表示需要一致的迭代.
如果您正在查看实现Map(HashMap,LinkedHashMap,TreeMap等)的特定类,那么您可以看到它如何实现keySet()函数以通过检查源来确定行为,您必须确实仔细查看算法,看看你要查找的属性是否被保留(即,当地图在迭代之间没有任何插入/删除时,一致的迭代顺序).例如,HashMap的源代码在这里(打开JDK 6):http://www.docjar.com/html/api/java/util/HashMap.java.html
从一个JDK到另一个JDK,它可能有很大差异,所以我绝对不会依赖它.
话虽这么说,如果一致的迭代顺序是你真正需要的东西,你可能想尝试一个LinkedHashMap.
只是为了好玩,我决定写一些代码,你可以用它来保证每次随机顺序.这很有用,因此您可以捕获依赖于订单的情况,但您不应该这样.如果你想依赖顺序,而不是像其他人所说的那样,你应该使用SortedMap.如果您只是使用Map并碰巧依赖于订单,那么使用以下RandomIterator将捕获它.我只会在测试代码时使用它,因为它会使用更多的内存然后不会这样做.
你也可以包装Map(或Set)让它们返回RandomeIterator,然后让你使用for-each循环.
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class Main
{
private Main()
{
}
public static void main(final String[] args)
{
final Map<String, String> items;
items = new HashMap<String, String>();
items.put("A", "1");
items.put("B", "2");
items.put("C", "3");
items.put("D", "4");
items.put("E", "5");
items.put("F", "6");
items.put("G", "7");
display(items.keySet().iterator());
System.out.println("---");
display(items.keySet().iterator());
System.out.println("---");
display(new RandomIterator<String>(items.keySet().iterator()));
System.out.println("---");
display(new RandomIterator<String>(items.keySet().iterator()));
System.out.println("---");
}
private static <T> void display(final Iterator<T> iterator)
{
while(iterator.hasNext())
{
final T item;
item = iterator.next();
System.out.println(item);
}
}
}
class RandomIterator<T>
implements Iterator<T>
{
private final Iterator<T> iterator;
public RandomIterator(final Iterator<T> i)
{
final List<T> items;
items = new ArrayList<T>();
while(i.hasNext())
{
final T item;
item = i.next();
items.add(item);
}
Collections.shuffle(items);
iterator = items.iterator();
}
public boolean hasNext()
{
return (iterator.hasNext());
}
public T next()
{
return (iterator.next());
}
public void remove()
{
iterator.remove();
}
}
Run Code Online (Sandbox Code Playgroud)