如何使用Java 8 Streams从ArrayList覆盖HashMap的值



我有这样的代码,其中我将覆盖ArrayList中Map的值
我想使用Streams和Lambda表达式编写此代码

List<Integer> list = new ArrayList<Integer>(arrayList);

Collections.sort(list, Collections.reverseOrder());
int i = 0;
Iterator<Entry<Integer, Integer>> itr = sortedMap.entrySet().iterator();
while(itr.hasNext()) {
Entry<Integer, Integer> pair = itr.next();
pair.setValue(list.get(i));
++i;
}

谢谢!

您可以将映射键转换为列表,然后使用IntStream同时循环通过映射键和排序列表:

List<Integer> list = new ArrayList<>(arrayList);
Collections.sort(list, Collections.reverseOrder());
List<Integer> mapKeys = new ArrayList<>(sortedMap.keySet());
Map<Integer,Integer> overwrittenMap = 
IntStream.range(0,mapKeys.size())
.boxed()
.collect(TreeMap::new, 
(map,i) -> map.put(mapKeys.get(i),list.get(i)),
Map::putAll);

与原始代码完全相同,即按降序设置现有sortedMap的值,可以作为实现

Iterator<Integer> values = arrayList.stream()
.sorted(Collections.reverseOrder())
.iterator();
sortedMap.replaceAll((key,value) -> values.next());

这假设列表和映射具有相同的大小,正如您在注释中确认的那样,即它不检查Iterator的末尾。

重要的是,sortedMap必须是一个SortedMap或一个维护订单的映射实现,这不包括问题标题中提到的HashMap。否则,对arrayList…的值进行排序是毫无意义的

这可以通过不同的方式实现:

  1. 将已排序映射的keySet转换为列表,并使用索引使用Collectors.toMap构建映射:
List<Integer> keys = new ArrayList<>(map.keySet());
Map<Integer, Integer> res = IntStream
.range(0, list.size())
.boxed()
.collect(Collectors.toMap(i -> keys.get(i), i -> list.get(i), (a, b)-> a, TreeMap::new));
System.out.println(res);
  1. 当按排序映射的键进行流式传输时,使用AtomicInteger及其getAndIncrement来引用列表中的更新元素:
AtomicInteger i = new AtomicInteger(0);
Map<Integer, Integer> res2 = map.keySet()
.stream()
.collect(Collectors.toMap(
k -> k, 
k -> list.get(i.getAndIncrement()), 
(a, b) -> a, 
TreeMap::new // or LinkedHashMap::new as keys are sorted
));
System.out.println(res2);
  1. 与以前的实现类似,可以使用映射的entrySet()forEach修改当前映射:
AtomicInteger j = new AtomicInteger(0);
map.entrySet().forEach(e -> e.setValue(list.get(j.getAndIncrement())));

可能需要添加额外的安全措施,例如,当地图和列表大小不同时,处理案例。

这些例子证明了这种任务的可行性,尽管任务本身似乎不是Stream API的适当应用。

最新更新