标签: collectors

Collectors.toSet()总是返回一个HashSet吗?合同是什么?

Javadoc说

返回将输入元素累积到新Set中的Collector.返回的Set的类型,可变性,可序列化或线程安全性无法保证; 如果需要更多地控制返回的Set,请使用toCollection(java.util.function.Supplier).

所以Collectors.toCollection(HashSet::new)在这里避免问题似乎是一个好主意(问题).

我的问题是,很难,因为我已经试过,我不能得到任何来自其他返回toSet()HashSet

这是我使用的代码:

public static void main(String[] args) {
    List<Integer> l = Arrays.asList(1,2,3);

    for (int i = 0 ; i++<1_000_000;){
        Class clazz = l.stream().collect(Collectors.toSet()).getClass();

        if (!clazz.equals(HashSet.class)) {
            System.out.println("Not a HashSet");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,为什么Javadoc说实际上没有保证,有......

java java-8 collectors

9
推荐指数
2
解决办法
2789
查看次数

为什么java收集流每次运行两次getter?

我有一个带有项目的List,其中每个项目都是一个对象,我有一个我感兴趣的getter方法.我想在完整列表上运行以总结所有这些getter结果.

当我使用java 8流时,它看起来像这样:

double currentProduction = itemList.stream().collect(
    Collectors.summingDouble((e) -> e.getProduction(param)));
Run Code Online (Sandbox Code Playgroud)

在普通的旧java中,它看起来像这样:

for (Item item : itemList) {
    currentProduction += item.getProduction(param);
}
Run Code Online (Sandbox Code Playgroud)

两种方法产生完全相同的结果,但我的记录器报告,对于每个项目实例,在java 8流解决方案的情况下,getProduction()方法运行TWICE.在普通的旧java列表迭代解决方案中,getProduction方法只是按预期运行一次.

由于getProduction方法成本很高,这对我来说是一个问题.

为什么是这样?我能做些什么(除了只使用for循环)?

java performance java-8 java-stream collectors

9
推荐指数
1
解决办法
397
查看次数

使用 Collectors.toMap 返回 LinkedHashMap

我该如何转换:

return this.subjects.entrySet()
            .stream()
            .collect(Collectors.toMap(e -> getArtistryCopy(e.getKey()), Map.Entry::getValue));
Run Code Online (Sandbox Code Playgroud)

要返回 LinkedHashMap 而不是地图?

如果您需要知道,this.subjects是一个LinkedHashMap<AbstractArtistries, ArrayList<AbstractCommand>>. AbstractArtistry 和 command 是我制作的两个自定义对象。我需要维持秩序。

getArtistryCopy() 返回 AbstractArtistry 的副本(这是关键)。

java linkedhashmap collectors

9
推荐指数
1
解决办法
5252
查看次数

java 8 Collector <String,A,R>不是一个功能界面,谁可以告诉为什么?

以下代码:

public class Test {
    public static void main(String[] args) {

        Stream.of(1,2,3).map(String::valueOf).collect(Collectors::toList)
    }
}
Run Code Online (Sandbox Code Playgroud)

intellij告诉我:

Collector<String, A, R> 不是功能界面

但是当我按如下方式修改代码时,一切都还可以,我不知道为什么?

public class Test {
    public static void main(String[] args) {

        Stream.of(1,2,3).map(String::valueOf).collect(Collectors.<String>toList());
    }
}
Run Code Online (Sandbox Code Playgroud)

java lambda java-8 java-stream collectors

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

Java groupingBy collector是否保留列表顺序?

考虑一个列表List<People>,其中元素按升序排序People.getAge().如果我们使用此列表进行分组Collectors.groupingBy(People::getCity),那么每个组/城市的结果列表是否仍按年龄排序?

在实践中,它确实似乎保留了秩序.我正在寻找保证.

该方法的Javadoc说:

如果不需要保留元素出现在生成的Map收集器中的顺序,则使用groupingByConcurrent(Function)可以提供更好的并行性能

我不确定这是否是指列表中的项目顺序.

java java-stream collectors

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

使用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万
查看次数

Java 8 stream.collect(... groupingBy(... mapping(... reduction)))减少BinaryOperator的使用

我使用了解决方案groupingBy,mapping并使用reducing 以下问题:在Java 8中优雅地创建带有对象字段的映射作为对象流的键/值.总结的目标是获得一张年龄为关键的地图和一个人的爱好Set.

我提出的解决方案之一(不好,但这不是重点)有一个奇怪的行为.

使用以下列表作为输入:

List<Person> personList = Arrays.asList(
     new Person(/* name */ "A", /* age */ 23, /* hobbies */ asList("a")),
     new Person("BC", 24, asList("b", "c")),
     new Person("D", 23, asList("d")),
     new Person("E", 23, asList("e"))
);
Run Code Online (Sandbox Code Playgroud)

以及以下解决方案:

Collector<List<String>, ?, Set<String>> listToSetReducer = Collectors.reducing(new HashSet<>(), HashSet::new, (strings, strings2) -> {
  strings.addAll(strings2);
  return strings;
});
Map<Integer, Set<String>> map = personList.stream()
                                          .collect(Collectors.groupingBy(o -> o.age, 
                                                                         Collectors.mapping(o -> o.hobbies, listToSetReducer)));
System.out.println("map = " + map);
Run Code Online (Sandbox Code Playgroud)

我有: …

java java-8 java-stream collectors

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

Java 8将List转换为Lookup Map

我有一个电台列表,在每个电台中都有一个收音机列表。我需要创建电台到电台的查找地图。我知道如何使用Java 8流forEach来做到这一点:

stationList.stream().forEach(station -> {
    Iterator<Long> it = station.getRadioList().iterator();
    while (it.hasNext()) {
        radioToStationMap.put(it.next(), station);
    }
});
Run Code Online (Sandbox Code Playgroud)

但是我相信应该有更简洁的使用方式Collectors.mapping()

有人可以帮忙吗?

java lookup java-8 java-stream collectors

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

Java:groupingBy subvalue as value

比方说,我有一个对象Person,其字段类型为FirstName和LastName.现在我也有一个List<Person>,我喜欢使用流.

现在我想生成一个Map<FirstName, List<LastName>>以便将具有相同名字的人分组.如何在不编写大量代码的情况下解决这个问题?到目前为止我的方法是

personList
.stream()
.collect(Collectors.groupingBy(
    Person::getFirstName,
    person -> person.getLastName() // this seems to be wrong
));
Run Code Online (Sandbox Code Playgroud)

但似乎这是分配地图价值的错误方法.我应该改变什么?或者我应该使用.reduce new HashMap<FirstName, List<LastName>>()作为初始值,然后通过将元素放入其中来聚合它?

java java-stream collectors

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

java.util.stream.Collectors:为什么使用数组实现summingInt?

标准收集器在summingInt内部创建一个长度为1的数组:

public static <T> Collector<T, ?, Integer>
summingInt(ToIntFunction<? super T> mapper) {
    return new CollectorImpl<>(
            () -> new int[1],
            (a, t) -> { a[0] += mapper.applyAsInt(t); },
            (a, b) -> { a[0] += b[0]; return a; },
            a -> a[0], CH_NOID);
}
Run Code Online (Sandbox Code Playgroud)

我想知道是否不可能仅定义:

private <T> Collector<T, Integer, Integer> summingInt(ToIntFunction<? super T> mapper) {
    return Collector.of(
            () -> 0,
            (a, t) -> a += mapper.applyAsInt(t),
            (a, b) -> a += b,
            a -> a
    );
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,因为似乎只是忽略了累加器。谁能解释这种行为?

java java-8 java-stream collectors

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