我已经看到了涉及该主题的答案,但想知道是否有人在示例中从哈希映射派生的键集和值列表将以不同的顺序排列键和值。我了解这些条目本身在哈希图中可能具有不确定的顺序,但是键和值的列表相对于彼此是否会乱序?
这里有一个简短的说明段:
public class App {
public static void main(String[] args) {
Map<String,String> stateCapitols = new HashMap<>();
stateCapitols.put("AL", "Montgomery");
stateCapitols.put("AK", "Juneau");
stateCapitols.put("CO", "Denver");
stateCapitols.put("FL", "Tallahassee");
stateCapitols.put("Indiana", "Indianapolis");
stateCapitols.keySet().stream().forEach(System.out::println);
System.out.println();
stateCapitols.values().stream().forEach(System.out::println);
}
}
在上面的示例中,AL
是否可以和Denver
(或其他任何值)出现在同一位置?
答案 0 :(得分:3)
让我们再来看一下Map
合同中有关迭代顺序的Java SE API语言:
某些地图实现(例如TreeMap类)对其顺序做出特定的保证;其他对象,例如HashMap类,则不会。
还有HashMap
:
此类不保证地图的顺序;特别是,它不能保证顺序会随着时间的推移保持恒定。
由于已明确声明HashMap迭代器没有顺序,因此即使在调用 same 方法之间也不能假设迭代是稳定的,更不用说在调用之间了>不同的方法name = input("Who are you looking for? :")
lst = [('Jeffery Medina','Officer','1254','101442.00','23'),('Katrina Peters','Officer','3423','94122.00','45'),('Kim Alan','Captain','6434','101592.00','29'),('Vincente Mendez','Officer','3235','110064.00','32'),('Chris Boalen','Captain','8769','50436.00','56'),('James Vito','Clerk','4451','23500.00','61'),('Terry George','Fireman','3342','93354.00','32'),('Zaid Dane','Officer','2345','84054.00','19'),('Ernesto Rodriguez','Officer','9091','87006.00','35'),('Josefine White','Fireman','3401','102228.00','26'),('Mario Infante','Officer','3234','84054.00','22'),('Juan Almonte','Fireman','4103','91272.00','50'),('Kevin Smith','Fireman','3450','111492.00','62'),('Abdum Smith','Captain','2234','95484.00','20'),('Juan Gomez','Clerk','9023','23890.00','49')]
for x in lst:
if name in x:
do_something_with_this_tuple(x)
和keySet()
。
values()
有一种方法entrySet()
可以完全满足您的需要:以配对键和值的方式遍历地图内容。这种方法可在您需要依赖一对对的两个部分时使用。
随着Java许可更改的生效,那些认为自己可能一直使用Oracle Java实现的人和组织现在正在寻找替代实现。依靠单个实施的未写细节是极其危险的,与甲骨文的许可和价格变更之前相比,现在甚至更加危险。
答案 1 :(得分:3)
HashMap不保证其迭代顺序。从原理上讲(例如,规范允许),例如,即使地图的内容未更改,键从一个迭代到下一个迭代的顺序也可以更改,或者键与相应值的迭代顺序不同。
这在HashMap规范中有所说明:
此类不保证地图的顺序;特别是,它不能保证顺序会随着时间的推移保持恒定。
在实践中,如果HashMap的初始化和填充方式完全相同,则HashMap的迭代顺序从一个迭代到下一个甚至从一个JVM调用到下一个都是稳定的。但是,应用程序依赖于此是不明智的。即使使用相同的内容填充地图,创建具有不同初始大小或负载因子的HashMap也会影响迭代顺序。 HashMap实现的确会不时变化,这也会影响迭代顺序。即使在JDK的修补程序或错误修正版本中,也会发生此类更改。不幸的是,历史表明,当迭代顺序更改时,应用程序将中断。因此,健壮的应用程序应努力避免对HashMap迭代顺序产生任何依赖性。
这在实践中很难做到。我知道JDK的一个(非公开)版本具有测试模式,该模式可以随机化HashMaps的迭代顺序。这可能有助于清除此类依赖性。
如果在迭代时需要关联HashMap的键和值,请获取HashMap的entrySet()并对其进行迭代。它提供了映射条目(键值对),因此保留了键和值之间的关系。
JDK中的替代Map实现提供了定义良好的迭代顺序。 TreeMap和ConcurrentSkipListMap基于提供的比较方法对它们的条目进行排序。 LinkedHashMap提供基于插入顺序的迭代顺序。 (它还提供了一种按访问顺序进行迭代的模式,该模式有时很有用,但其行为通常令人惊讶。)
请注意,Java 9中引入的不可修改的集合(Set.of,Map.of等)提供了随机迭代顺序。每次运行JVM的顺序将有所不同。这应该有助于应用程序避免无意间依赖迭代顺序。