给出一个唯一值子列表的列表(也就是说,两个不同的子列表不能共享相同值的元素)-例如:
List[List[1, 1, 1], List[2], List[4, 4], List[7]]
如何将其转换为具有(值,大小)键值对的地图?
这将导致:
{
1 : 3
2 : 1
4 : 2
7 : 1
}
将列表定义为values
,我假设人们可以使用流并这样收集地图:
values.stream().collect(Collectors.toMap(Integer::intValue, ? ));
当前不确定第二个参数要输入什么内容,因为它需要value mapper
,但不允许在任何子列表上调用.size()
。
答案 0 :(得分:7)
使用Collectors.toMap
时,您需要指定如何从流的每个元素中获取键和值。 Integer::intValue
在这里不起作用,因为您的流元素是列表,而不是整数。
对于键,获取列表的第一个元素。 (这假定内部列表都是非空的。)对于该值,请传递size
方法引用。
values.stream()
.collect(Collectors.toMap(list -> list.get(0), List::size));
答案 1 :(得分:1)
您可以展平列表,然后使用Collectors.groupingBy(Function.identity(),Collectors.counting())之类的东西。 但是在这种情况下,我会说一个好的(嵌套的)for循环可能更容易读写。
List<List<Integer>> lst = Arrays.asList(Arrays.asList(1,1,1),Arrays.asList(2),Arrays.asList(4,4),Arrays.asList(7));
Map<Integer,Integer> result= new HashMap<Integer,Integer>();
System.out.println(lst);
//[[1, 1, 1], [2], [4, 4], [7]]
for(List<Integer> sub:lst){
for(int n:sub){
Integer last=result.get(n);
int newCount=(last==null?0:last)+1;
result.put(n, newCount);
}
}
System.out.println(result);
//{1=3, 2=1, 4=2, 7=1}
答案 2 :(得分:1)
我认为@rgettman's answer是最优雅的。但是,它假定所有列表都是非空的。当然,只需在.filter(list -> !list.isEmpty())
归约运算之前添加collect
即可轻松解决此问题。
这是另一种方法,不再将列表视为“二维”,即List<List<Integer>>
,而是将其展平为Integer
s的流。
Map<Integer, Long> map = lists.stream()
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));