标签: collectors

使用stream()创建由2个列表组成的地图.在Java中收集

例如,有两个列表:

List<Double> list1 = Arrays.asList(1.0, 2.0);
List<String> list2 = Arrays.asList("one_point_zero", "two_point_zero");
Run Code Online (Sandbox Code Playgroud)

使用Stream,我想创建一个由这些列表组成的映射,其中list1用于键,list2用于值.为此,我需要创建一个辅助列表:

List<Integer> list0 = Arrays.asList(0, 1);
Run Code Online (Sandbox Code Playgroud)

这是地图:

Map<Double, String> map2 = list0.stream()
                .collect(Collectors.toMap(list1::get, list2::get));
Run Code Online (Sandbox Code Playgroud)

list0用于list1 :: get和list2 ::开始工作.没有创建list0有没有更简单的方法?我尝试了以下代码,但它不起作用:

Map<Double, String> map2 = IntStream
                .iterate(0, e -> e + 1)
                .limit(list1.size())
                .collect(Collectors.toMap(list1::get, list2::get));
Run Code Online (Sandbox Code Playgroud)

java-8 java-stream collectors

8
推荐指数
2
解决办法
1万
查看次数

为什么Collectors.toList()不能处理原始集合?

(这可能与/sf/answers/2121852421/有关,但我恐怕还是没有得到它.所以我这样问我的问题,希望它能够得出一个我可以更容易理解的答案.)

通常,当我有一个Stream时,我可以使用Collectors类中的一个静态方法将其转换为集合:

List<String> strings = Stream.of("this", "is", "a", "list", "of", "strings")
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

然而,类似的过程不适用于原始流,正如其他人注意到的那样:

IntStream.of(3, 1, 4, 1, 5, 9)
    .collect(Collectors.toList());  // doesn't compile
Run Code Online (Sandbox Code Playgroud)

我可以这样做:

IntStream.of(3, 1, 4, 1, 5, 9)
    .boxed()
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

或者我可以这样做:

IntStream.of(3, 1, 4, 1, 5, 9)
    .collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll);
Run Code Online (Sandbox Code Playgroud)

问题是,为什么Collectors.toList()只为原始流做这个?难道没有办法指定包装类型吗?如果是这样,为什么这不起作用:

IntStream.of(3, 1, 4, 1, 5, 9)
    .collect(Collectors.toCollection(ArrayList<Integer>::new)); // nope
Run Code Online (Sandbox Code Playgroud)

任何见解将不胜感激.

java java-8 collectors

7
推荐指数
1
解决办法
1503
查看次数

Java API Streams在Map中收集流,其中value是TreeSet

有一个Student类,它们有name, surname, age字段和getter.

给定一个Student对象流.

如何调用一个collect方法,使得它将返回Map键所在的位置age,Student并且值TreeSet包含surname具有此类的学生age.

我想用Collectors.toMap(),但卡住了.

我以为我可以这样做并将第三个参数传递给toMap方法:

stream().collect(Collectors.toMap(Student::getAge, Student::getSurname, new TreeSet<String>()))`.
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream collectors

7
推荐指数
1
解决办法
144
查看次数

使用流从现有列表创建不可变列表

有一个Person对象列表.

List<Person> persons = generatePersons();

使用它创建一个unmodifiableList.

List<Person> unmodifiableList = Collections.unmodifiableList(persons);

据我所知,unmodifiableList这不支持添加/删除/设置操作.同时它不是不可变的,因为它引用了现有的可修改列表,persons并且每当对persons列表进行更改时,更改也会反映出来unmodifiableList.

以这种方式创建不可变列表.

List<Person> immutableList = Collections.unmodifiableList(new ArrayList<>(persons));

这会创建一个不可变列表,因为正在使用转换构造函数.不能执行添加/删除/设置操作,immutableList也不能persons反映原始列表中的任何更改immutableList.让我们假设Person对象也是不可变的.

现在,我想使用流创建这两个列表.

第一个,我创建使用:

List<Person> unmodifiablePersons = persons.stream() .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));

我迷失了通过流创建等效的immutableList.

我怎样才能做到这一点?

编辑:

Person在原始列表中添加了一个新对象persons并打印了persons列表的大小和unmodifiablePersons.两者都给我相同的大小.因此,变化正在反映unmodifiablePersons,因此它不是一成不变的.我在这里错过了什么吗?

编辑2

愚蠢.本应该通过文档.unmodifiablePersons确实是一个不可改变的清单.此外,新Person对象在unmodifiablePersons创建之前添加,因此上述观察.超级傻.

java collections java-8 java-stream collectors

7
推荐指数
2
解决办法
955
查看次数

如何将地图地图列表合并到地图中?

你能帮帮我Java Streams吗?

正如你从标题中看到的,我需要合并List<Map<String, Map<String, Genuineness>>>Map<String, Map<String, Genuineness>>.

该列表表示为List<Map<String, Map<String, Genuineness>>>:

[  
   {  
      "USER_1":{  
         "APP_1":{  
            "total":1,
            "totalGenuine":1,
            "totalDevelopment":1
         }
      },
      "USER_2":{  
         "APP_1":{  
            "total":1,
            "totalGenuine":1,
            "totalDevelopment":1
         },
         "APP_2":{  
            "total":2,
            "totalGenuine":2,
            "totalDevelopment":2
         }
      }
   },
   {  
      "USER_1":{  
         "APP_1":{  
            "total":1,
            "totalGenuine":1,
            "totalDevelopment":1
         }
      },
      "USER_2":{  
         "APP_1":{  
            "total":1,
            "totalGenuine":1,
            "totalDevelopment":1
         },
         "APP_2":{  
            "total":2,
            "totalGenuine":2,
            "totalDevelopment":2
         }
      }
   }
]
Run Code Online (Sandbox Code Playgroud)

因此,正如您所看到的,重复的键可能无处不在.我的目标是Map<String, Map<String, Genuineness>>通过合并将它们组合在一起Genuineness.合并Genuineness只是意味着返回一个新的对象与总结了值total,totalGenuinetotalDevelopment.

这是我的实现失败:

final Map<String, …
Run Code Online (Sandbox Code Playgroud)

java hashmap java-stream collectors

7
推荐指数
1
解决办法
91
查看次数

Using Java lambda to build map from two maps

I have some code that I need help with ... I'm trying to build a map using two maps as a source and at the same time using java lambdas

Map<String, List<String>> motorsMapping = new HashMap<>();

motorsMapping.put("CAR", Collections.singletonList("AUDI"));
motorsMapping.put("CAR_AND_BIKE", Arrays.asList("AUDI", "BMW"));
motorsMapping.put("BIKE", Collections.singletonList("BMW"));

Map<String, List<String>> models = new HashMap<>();
models.put("AUDI", Arrays.asList("A1", "Q2"));
models.put("BMW", Arrays.asList("X1", "X5"));


motorsMapping.keySet().forEach(key -> {
     Map<String, List<String>> result = new HashMap<>();
     result.put(key, new ArrayList<>());
     motorsMapping.get(key).forEach(value -> models.getOrDefault(value, Collections.emptyList()).forEach(property -> result.get(key).add(property)));
});
Run Code Online (Sandbox Code Playgroud)

I can do that with the …

java lambda java-8 java-stream collectors

7
推荐指数
1
解决办法
145
查看次数

java 8 按不同计数进行分组

SELECT Count(1) AS total,
          'hello' AS filter,
          field1 AS field1,
          Count(DISTINCT field2) AS total_field2
   FROM table
   WHERE field = true
     AND status = 'ok'
      GROUP  BY field1
Run Code Online (Sandbox Code Playgroud)

怀疑如何使用java8制作地图来存储以下结果。映射键必须是字段field1,映射值必须是total_field2字段。

也就是说,我需要使用字段 field1 和计数字段 field2 对列表进行分组

对于我的总字段

myList.stream().collect(Collectors.groupingBy(MyObject::getField1, Collectors.counting())) 
// this is just counting the records grouped by field1
Run Code Online (Sandbox Code Playgroud)

我的结果是正确的total_field1:{4=55, 6=31}

对于 field2,我需要这样的东西,但它只是给我一个记录

myList.stream().filter(distinctByKey(MyObject::getField2))
.collect(Collectors.groupingBy(MyObject::getField1, Collectors.counting()));

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }
Run Code Online (Sandbox Code Playgroud)

结果total_Field2:{4=31}

应该返回 …

java grouping java-8 java-stream collectors

7
推荐指数
2
解决办法
9639
查看次数

将流映射到另一个对象的实例

我有一个类CarPart定义为:

class CarPart {
  String name;
  BigDecimal price;
  Supplier supplier;
}
Run Code Online (Sandbox Code Playgroud)

一个类Report

class Report {
   List<Part> parts;
   BigDecimal total;
}
Run Code Online (Sandbox Code Playgroud)

和一个班级Part

class Part {
  String name;
  String supplierName;
}
Run Code Online (Sandbox Code Playgroud)

给定 a Stream<CarPart> carParts,我需要创建一个Report对象。

我处理这个问题的想法是创建一个Map<List<Part>, BigDecimal>,其中List<Part>是转换CarPart对象的列表,BigDecimal是给定流中所有汽车零件的价格总和。之后,我可以访问Map<>包含单个条目的 ,并且可以创建一个新的Report.

我开始这样做,但我不知道如何收集它。在.map我在下面做之后,我实际上有一个,Map<Part, BigDecimal>但我需要总结Part一个列表中的所有对象,并将所有对象相BigDecimal加以创建Report.

   carParts.stream()
           .map(x -> {
               return new AbstractMap.SimpleEntry<>(new Part(x.getName(), x.supplier.getName()), x.getPrice());
           }) …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream collectors

7
推荐指数
1
解决办法
100
查看次数

Java 收集器提供输入列表

我正在尝试实现一个简单的收集器,它采用收集器列表,并同时以略有不同的方式从流中收集值。

它与 非常相似Collectors.teeing,但不同之处在于

  1. 收到收藏家列表,而不是仅仅两个
  2. 要求所有收集器产生相同类型的值

我想要的类型签名是

public static <T, R> Collector<T, ?, List<R>> list(
      final List<Collector<T, ?, R>> downstreamCollectors);
Run Code Online (Sandbox Code Playgroud)

创建此类收集器的一种方法是递归地配对发球收集器,如下所示:

public static <T, R> Collector<T, ?, List<R>> list(
    final List<Collector<T, ?, R>> downstreamCollectors) {
  return listrec(
      Collectors.collectingAndThen(downstreamCollectors.get(0), List::of),
      downstreamCollectors.stream().skip(1).toList());
}

private static <T, R> Collector<T, ?, List<R>> listrec(
    final Collector<T, ?, List<R>> teedCollectors,
    final List<Collector<T, ?, R>> downstreamCollectors) {
  if (downstreamCollectors.size() == 0) {
    return teedCollectors;
  } else {
    return listrec(
        teeing(
            teedCollectors,
            downstreamCollectors.get(0),
            (l, s) -> Stream.concat(l.stream(), …
Run Code Online (Sandbox Code Playgroud)

java functional-programming type-inference java-stream collectors

7
推荐指数
1
解决办法
779
查看次数

使用 Java 8 创建 ImmutableMap

如何使用 Java Stream API 编写以下方法?

public Map<String, String> getMap() {
    Map<String, String> mapB = new HashMap<>();
    
    for (String parameterKey : listOfKeys) {
        String parameterValue = mapA.get(parameterKey);
        
        mapB.put(parameterKey, Objects.requireNonNullElse(parameterValue, ""));
    }
    return ImmutableMap.copyOf(mapB);
}
Run Code Online (Sandbox Code Playgroud)

我尝试过这样的事情:

return listOfKeys.stream()
    .map(firstMap::get)
    .collect( ? )
Run Code Online (Sandbox Code Playgroud)

但我不知道如何从这里继续。

java guava java-stream collectors

7
推荐指数
1
解决办法
1480
查看次数