import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 按value值对map进行排序,输出前k个key
*/
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>(){{
put("java",3);
put("C++",4);
put("Python", 2);
put("C#", 0);
}};
int k = 2;
System.out.println(map.entrySet().stream().sorted((o1,o2)->o2.getValue() - o1.getValue()).limit(k).map(
Map.Entry::getKey).collect(Collectors.toList()).toString());
}
}
解释
map变量声明时添加内容初始化
Map<String, Integer> map = new HashMap<String, Integer>(){{
put("java",3);
put("C++",4);
put("Python", 2);
put("C#", 0);
}};
sorted:
map.entrySet().stream().sorted((o1,o2)->o2.getValue() - o1.getValue())
// sorted 方法的函数签名
Stream<T> sorted(Comparator<? super T> comparator);
// Comparator 接口中的抽象方法
int compare(T o1, T o2);
boolean equals(Object obj);
我们知道,函数式接口要求接口里面只能有一个抽象方法,咋一看, Comparator 接口中有俩抽象方法,似乎不符合函数式接口的要求,但其实是符合的,因为第二个 euqals 抽象方法其实是继承自 Object,从 Object 继承的方法是不计入接口抽象方法数量的。所以,对于 Comparator 接口,我们只需要提供一个满足 compare 定义的函数方法就行了。
limit:
map.entrySet().stream().sorted((o1,o2)->o2.getValue() - o1.getValue()).limit(k)
limit 方法用于截取流中前 k 个元素,类似的还有 skip 方法,用于跳过前 k 个元素。
map:
map.entrySet().stream().sorted((o1,o2)->o2.getValue() - o1.getValue()).limit(k).map(
Map.Entry::getKey)
// map 方法的函数签名
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
// Function 接口中的抽象方法
R apply(T t);
这里我们用了 Lambda 表达式方法的另一种形式,即不实例化类,直接从类中引用已有方法。
collect:
map.entrySet().stream().sorted((o1,o2)->o2.getValue() - o1.getValue()).limit(k).map(
Map.Entry::getKey).collect(Collectors.toList())
//collect 方法的函数签名
<R, A> R collect(Collector<? super T, A, R> collector);
collect 方法接收一个 Collector 对象,用于收集流,Collector 接口不是一个函数式接口。