Joh*_*ess 6 java java-8 java-stream collectors
我想把数字的频率放在一个TreeMap频率为频率的频率和频率为a 的数字中ArrayList.
我有两个问题:
1)我在第一个参数中得到"非静态方法无法从静态上下文引用"错误(AFAIK流引用一个对象 - 发生了什么?)
2)Collectors.toMap()有4个参数 - 看起来参数4需要使用新的TreeMap进行初始化>,参数2可以是ArrayList add()函数,参数3可以是null(可能).这是怎么做到的?
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> array = Arrays.asList(1, 2, 4, 5, 6, 4, 8, 4, 2, 3);
Map<Integer, Long> m = array.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(m);
TreeMap<Long, List<Integer>> tm = m.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getValue, ...));
Run Code Online (Sandbox Code Playgroud)
目前我无法使用如何从 https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html到我需要的地方.
我不会使用流来创建倒置的地图.相反,我会这样做:
Map<Long, List<Integer>> tm = new TreeMap<>();
m.forEach((num, freq) -> tm.computeIfAbsent(freq, k -> new ArrayList<>()).add(num));
System.out.println(tm); // {1=[1, 3, 5, 6, 8], 2=[2], 3=[4]}
Run Code Online (Sandbox Code Playgroud)
由于创建倒置贴图的代码很短,您可以使用Collectors.collectingAndThen一步创建频率和倒置贴图:
TreeMap<Long, List<Integer>> invertedFrequenciesMap = array.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(Function.identity(), Collectors.counting()),
map -> {
TreeMap<Long, List<Integer>> tm = new TreeMap<>();
map.forEach((num, freq) ->
tm.computeIfAbsent(freq, k -> new ArrayList<>()).add(num));
return tm;
}));
Run Code Online (Sandbox Code Playgroud)
你的推理几乎是正确的......只是第3个参数是你为同一个键合并你的值的地方 - 所以你不能省略它.
TreeMap<Long, List<Integer>> tm = m.entrySet().stream()
.collect(Collectors.toMap(
Entry::getValue,
x -> {
List<Integer> list = new ArrayList<>();
list.add(x.getKey());
return list;
},
(left, right) -> {
left.addAll(right);
return left;
},
TreeMap::new));
Run Code Online (Sandbox Code Playgroud)
我觉得Collectors.groupingBy比Collectors.toMap实现你想要的更有意义:
Map<Long, List<Integer>> tm =
m.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, // group the entries by the
// value (the frequency)
TreeMap::new, // generate a TreeMap
Collectors.mapping (Map.Entry::getKey,
Collectors.toList()))); // the
// value of the output TreeMap
// should be a List of the
// original keys
Run Code Online (Sandbox Code Playgroud)
您可以替换Collectors.toList()使用Collectors.toCollection(ArrayList::new),以确保输出的值Map是ArrayListS(虽然目前执行的toList()已经导致java.util.ArrayList实例).
对于您的示例输入,这会产生以下结果TreeMap:
{1=[1, 3, 5, 6, 8], 2=[2], 3=[4]}
Run Code Online (Sandbox Code Playgroud)