Java:将List <List>转换为地图

时间:2019-09-24 20:58:41

标签: java dictionary java-stream

给出一个唯一值子列表的列表(也就是说,两个不同的子列表不能共享相同值的元素)-例如:

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()

3 个答案:

答案 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()));