使用Java 8将列表转换为映射

5

我正在使用Java 8编写一个通过值对映射进行排序的代码。

我已经完成了大部分工作,但是我不知道如何使用Java 8功能将列表转换为映射表。

public class SortMapByValue {
public static void main(String[] args) {
    HashMap<String, Integer> map = new HashMap<>();
    map.put("A", 3);
    map.put("V", 1);
    map.put("Anss", 9);
    map.put("D", 5);
    map.put("E", 2);
    map.put("F", 10);

    HashMap<String, Integer> newMap = new LinkedHashMap<>();

    List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());


    Collections.sort(list, (o1, o2) -> o1.getValue() - o2.getValue());

    // Need to this using Java 8 -- start

    for (Entry<String, Integer> entry : list) {
        newMap.put(entry.getKey(), entry.getValue());
    } 

    // Need to this using Java 8 -- end

    newMap.forEach((k, v) -> System.out.println("Key : " + k + " Value : " + v));

    }
}

1
我正在处理按值对地图进行排序的问题 => Entry::comparingByValue - Eugene
2个回答

5
如果您想根据值对Map进行排序,请使用Entry.comparingByValue(),然后将它们收集到LinkedHashMap中:
Map<String,Integer> result =   map.entrySet()
       .stream()
       .sorted(Entry.comparingByValue())
       .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a,b) -> b, LinkedHashMap::new));

Java-8中有三个重载的toMap方法,上面的一个方法有4个参数,即
public static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper,
                                                            Function<? super T,? extends U> valueMapper,
                                                            BinaryOperator<U> mergeFunction,
                                                            Supplier<M> mapSupplier)

参数:

keyMapper - 用于生成键的映射函数

valueMapper - 用于生成值的映射函数

mergeFunction - 合并函数,用于解决与Map.merge(Object, Object, BiFunction)相同键关联的值之间的冲突

mapSupplier - 返回新的、空的Map函数,将结果插入其中


除了(a,b)->a, LinkedHashMap::new)之外,我都理解了。这里发生了什么?我的意思是,我可以看到你创建了一个新的LinkedHashMap实例,但(a,b) -> a是在做什么? - testMyUnderstanding
第三个参数是merge函数。它接受两个映射并将它们合并成一个映射。我认为在这个例子中假设不会有重复的键,因此实际上不需要合并两个映射,因此合并函数可以简单地返回第一个映射,因为它实际上永远不会被调用。你可以把一个null放在那里,但我没有测试过。toMap - K.Nicholas
第三个函数是uniqueKeyMapper。如果您的列表中有重复的键,则可以选择要继续使用哪一个。 - Rahul B
1
更新了,我同意,但是既然我们正在处理“Map”数据,我认为合并函数没有任何用处。 @YassinHajaj - Ryuzaki L
1
@Deadpool 在这个例子中我们只有唯一的键,但是我认为遵循算法100%更加清晰。顺便说一句,回答得不错。 - Yassin Hajaj
显示剩余2条评论

1
Map map = list.stream().collect(
    Collectors.toMap(
        entry -> entry.getKey(), // keyMapper
        entry -> entry.getValue(), // valueMapper
        (first, second) -> first,  // mergeFunction
        () -> new LinkedHashMap<>() // mapFactory
    )
);

请查看StreamCollectors

你甚至可以这样做:

public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("A", 3);
        map.put("V", 1);
        map.put("Anss", 9);
        map.put("D", 5);
        map.put("E", 2);
        map.put("F", 10);

        Map newMap = map.entrySet().stream()
            .sorted(Map.Entry.comparingByValue())
            .collect(
                Collectors.toMap(
                    entry -> entry.getKey(), // keyMapper
                    entry -> entry.getValue(), // valueMapper
                    (first, second) -> first,  // mergeFunction
                    () -> new LinkedHashMap<>() // mapFactory
                )
            );

        newMap.forEach((k, v) -> System.out.println("Key : " + k + " Value : " + v));

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接