[英]How to overwrite values of HashMap from ArrayList using Java 8 Streams
I have this code in which I am overwriting values of Map from an ArrayList.我有这段代码,我在其中覆盖了 ArrayList 中 Map 的值。
I want to write this code using Streams and Lambda expression我想使用 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;
}
Thank You!谢谢你!
You could convert the map keys to a list, and then loop through both map keys and sorted list simultaneously using IntStream:您可以将映射键转换为列表,然后使用 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);
This can be implemented in different ways:这可以通过不同的方式实现:
keySet
of the sorted map into list and use indexes to build a map using Collectors.toMap
:将已排序映射的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);
AtomicInteger
and its getAndIncrement
when streaming by keys of the sorted map to refer the element in the list with the updates:在按排序映射的键流式传输时使用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);
forEach
of the map's entrySet()
:与之前的实现类似,可以使用forEach
地图的entrySet()
修改当前地图:AtomicInteger j = new AtomicInteger(0);
map.entrySet().forEach(e -> e.setValue(list.get(j.getAndIncrement())));
Extra safety measures may need to be added, for instance, handling of the case when the map and the list are of different size.可能需要添加额外的安全措施,例如处理地图和列表大小不同的情况。
These examples prove the feasibility of such task, though the task itself does not seem to be an appropriate application of Stream API.这些示例证明了此类任务的可行性,尽管任务本身似乎不是 Stream API 的合适应用。
Doing literally the same as your original code, ie set the values of the existing sortedMap
in descending order, can be achieved as与原始代码完全相同,即按降序设置现有sortedMap
的值,可以实现为
Iterator<Integer> values = arrayList.stream()
.sorted(Collections.reverseOrder())
.iterator();
sortedMap.replaceAll((key,value) -> values.next());
This assumes that the list and the map have the same size, as you acknowledged in a comment, ie it does not check for the end of the Iterator
.这假设列表和地图具有相同的大小,正如您在评论中所承认的那样,即它不检查Iterator
的结尾。
It's important that sortedMap
truly has to be a SortedMap
or a map implementation maintaining an order in general, which excludes the HashMap
mentioned in the title of your question.重要的是sortedMap
确实必须是SortedMap
或通常维护顺序的地图实现,这不包括问题标题中提到的HashMap
。 Otherwise, it's pointless to sort the values of the arrayList
…否则,对arrayList
的值进行排序是没有意义的……
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.