简体   繁体   English

使用Streaming API转换地图列表中的值

[英]Convert values in a List of Maps with Streaming API

I have a list of maps with non distinctive keys and like to modify each map value with Streaming API . 我有一个具有非唯一键的地图列表,并且喜欢使用Streaming API修改每个地图值。 The result should be a new list, the original one has to remain unchanged. 结果应该是一个新列表,原始列表必须保持不变。

Example data: 示例数据:

// [ {jpg=firstImage.jpg, png=firstImage.png}, {jpg=secondImage.jpg, png=secondImage.png} ]
Map<String, String> map1 = new HashMap<>();
map1.put("jpg", "firstImage.jpg");
map1.put("png", "firstImage.png");
Map<String, String> map2 = new HashMap<>();
map2.put("jpg", "secondImage.jpg");
map2.put("png", "secondImage.png");
List<Map<String, String>> list = new ArrayList<>();
list.add(map1);
list.add(map2);

Let's assume I want to convert the filename to upper case. 假设我想将文件名转换为大写。 With distinctive values I could do the following: 利用独特的价值观,我可以做到以下几点:

Map<String, String> copy = list.stream()
                .flatMap(e -> e.entrySet().stream())
                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toUpperCase()));

But flatMap does not work when keys aren't distinctive, and it would destroy my List<Map<String, String>> structure. 但是,当键不具有唯一性时, flatMap不起作用,它将破坏我的List<Map<String, String>>结构。 I know that the structure is bad, but I can't change it. 我知道结构不好,但是我无法更改。

Expected outcome: 预期结果:

// [ {jpg=FIRSTIMAGE.JPG, png=FIRSTIMAGE.PNG}, {jpg=SECONDIMAGE.JPG, png=SECONDIMAGE.PNG} ]

I'd like to achieve this with Streaming API and avoid nested loops if possible. 我想通过Streaming API实现此目标,并尽可能避免嵌套循环。

You can't use flatMap , because this way you would concat all Entries in a single Stream and thus loose the possibility to get them back. 您不能使用flatMap ,因为这样您将在单个Stream中合并所有Entries,从而失去了将它们取回的可能性。

You need to convert each individual element from your List , like this for example: 您需要转换List每个元素,例如:

  List<Map<String, String>> result = list.stream()
            .map(map -> map.entrySet().stream()
                          .collect(Collectors.toMap(
                                  Map.Entry::getKey, 
                                  e -> e.getValue().toUpperCase())))
            .collect(Collectors.toList());

    System.out.println(result);
    // [{jpg=FIRSTIMAGE.JPG, png=FIRSTIMAGE.PNG}, {jpg=SECONDIMAGE.JPG, png=SECONDIMAGE.PNG}]

Here's an option 这是一个选择

    list.forEach(map -> map.replaceAll((t, f) -> f.toUpperCase()));

I am modifying the existing maps in your list. 我正在修改您列表中的现有地图。 And it's not using streams. 而且它不使用流。

Edit: Thanks to VGR for the great simplification. 编辑:感谢VGR的极大简化。

Edit: Since you need to leave your original structure unmodified, Eugene's solution is fine. 编辑:由于您需要保持原始结构不变,因此Eugene的解决方案很好。 You may also apply replaceAll() on a copy. 您也可以在副本上应用replaceAll() One example: 一个例子:

    List<Map<String, String>> result = new ArrayList<>(list);
    list.replaceAll(m -> {
                Map<String, String> newMap = new HashMap<>(m);
                newMap.replaceAll((t, f) -> f.toUpperCase());
                return newMap;
            });

Or yet a different approach, this one with a stream: 还是另一种方法,该方法带有流:

    List<Map<String, String>> result = list.stream()
            .map(m -> {
                Map<String, String> newMap = new HashMap<>(m);
                newMap.replaceAll((t, f) -> f.toUpperCase());
                return newMap;
            })
            .collect(Collectors.toList());

Which to prefer, I'd say it's mostly a matter of taste. 我想说哪个更喜欢味道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM