标签: collectors

Java 8 Stream Collectors - 使用多个存储桶中的对象创建 Map 的收集器

以下代码有效且可读,但在我看来,我认为不需要中间操作。我编写了这个简化版本,因为实际代码是一个更大过程的一部分。

我有一个Collectionof Widget,每个都有一个名称和多种类型(由WidgetType枚举的常量表示)。这些多种类型都是可以获取的,Stream<WidgetType>但如果有必要,我可以将它们作为其他类型返回。(出于各种原因,强烈希望将它们作为 a 返回,Stream<WidgetType>因为稍后在实际代码中如何使用这些小部件。)

这些小部件被添加到 ,EnumMap<WidgetType, List<Widget>>然后被翻译成EnumMap<WidgetType, Widget[]>.

如果每个都Widget只有一个WidgetType,这将是一个微不足道的解决方案,但是,由于任何 Widget 都可能有 1 个或多个类型,因此我会被Collectors.groupingBy()方法的语法(及其重载)绊倒。

这是代码示例,再次,功能齐全,并为我提供了我需要的确切结果。

class StackOverFlowExample {

    private final Map<WidgetType, Widget[]> widgetMap = new EnumMap<>(WidgetType.class);

    public static void main(String[] args) { new StackOverFlowExample(); }

    StackOverFlowExample() {
        Collection<Widget> widgetList = getWidgetsFromWhereverWidgetsComeFrom();

        {
            final Map<WidgetType, List<Widget>> intermediateMap = new EnumMap<>(WidgetType.class);
            widgetList.forEach(w ->
                    w.getWidgetTypes().forEach(wt -> {
                        intermediateMap.putIfAbsent(wt, new ArrayList<>());
                        intermediateMap.get(wt).add(w);
                    }) …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream collectors

3
推荐指数
1
解决办法
671
查看次数

Collectors.groupingBy 的自定义收集器无法按预期工作

考虑简单的类Foo

public class Foo {

    public Float v1;
    public Float v2;
    public String name;

    public Foo(String name, Float v1, Float v2) {
        this.name = name;
        this.v1 = v1;
        this.v2 = v2;
    }

    public String getName() {
        return name;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我有一个Foos的集合,我想将它们按Foo::getName. 我写了一个自定义收集器来做到这一点,但它似乎没有按预期工作。更准确地说,combiner()永远不会被调用。为什么?

public class Main {

    public static void main(String[] args) {

        List<Foo> foos = new ArrayList<>();
        foos.add(new Foo("blue", 2f, 2f));
        foos.add(new Foo("blue", 2f, 3f));
        foos.add(new Foo("green", 3f, 4f));

        Map<String, Float> fooGroups …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream collectors

3
推荐指数
1
解决办法
217
查看次数

将整数列表转换为逗号分隔的字符串?

我试图将整数列表转换为逗号分隔整数的字符串。

Collectors.joining(CharSequence delimiter) - 返回一个收集器,它按遇到顺序连接输入元素,由指定的分隔符分隔。

List<Integer> i = new ArrayList<>();    //  i.add(null);
for (int j = 1; j < 6; j++) {
    i.add(j);
}
System.out.println(i.stream().collect(Collectors.joining(","))); // Line 8
Run Code Online (Sandbox Code Playgroud)

我在第 8 行出错。

有没有办法通过 Java 8 中的流来做到这一点?

更新:

如果我用"1", "2", "3","4","5". 有用。

java integer java-8 java-stream collectors

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

将 Java Stream 计数为整数,而不是长整型

我需要计算一些特殊捆绑包的出现次数。

Map<Integer,Integer> countBundles(){
    return bundles.stream()
        .bla()
        .bla()
        .bla()
        .collect(groupingBy(Bundle::getId), counting()));
}
Run Code Online (Sandbox Code Playgroud)

此代码无法编译,因为计数返回 Long。有什么漂亮的方法返回 Map<Integer, Integer> 吗?

我有这个想法,但是很难看

  map.entrySet().stream()
     .collect(toMap(Map.Entry::getKey, entry -> (int) entry.getValue().longValue()));
Run Code Online (Sandbox Code Playgroud)

java java-stream collectors

3
推荐指数
1
解决办法
2363
查看次数

无法并行工作的自定义收集器

我制作了一个自定义收集器,它使用 MessageDigest 来创建哈希。一般来说,MessageDigest 不能并行工作。我看到的问题在于combiner()方法。无法组合两个 MessageDigest 对象。当我返回 null 时,它似乎可以工作,但如果我抛出一个,UnsupportedOperationException它就会失败。实现不支持并行操作的收集器的典型方法是什么?

class ChecksumCollector implements Collector<String, MessageDigest, ByteBuffer> {
    private String algorithm;

    ChecksumCollector(final String algorithm) {
        this.algorithm = algorithm;
    }

    @Override
    public Supplier<MessageDigest> supplier() {
        return () -> {
            try {
                return MessageDigest.getInstance(algorithm);
            } catch (NoSuchAlgorithmException e) {
                throw new UnsupportedOperationException("Could not find MessageDigest for algorithm " + algorithm, e);
            }
        };
    }

    @Override
    public BiConsumer<MessageDigest, String> accumulator() {
        return (md, s) -> md.update(s.getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public BinaryOperator<MessageDigest> combiner() { …
Run Code Online (Sandbox Code Playgroud)

java java-stream collectors

3
推荐指数
1
解决办法
290
查看次数

groupingBy 使用布尔值,但添加自定义字符串作为键

我有下面的代码并基于布尔值进行 groupingBy

Map<Boolean, List<Test>> products = testList
        .stream()
        .collect(Collectors.groupingBy(Test::isValidUser));
        
Run Code Online (Sandbox Code Playgroud)

我想把它收集起来Map<String, List<Test>

基于布尔值,想要将自定义键添加为“有效”和“无效”。

如果为isValidUsertrue,则要将密钥添加为“有效”,否则密钥应为“无效”

在 Java 11 中是否有可能做到这一点?

注意:没有在Test类中添加String变量

java collections java-8 java-stream collectors

3
推荐指数
1
解决办法
738
查看次数

Java-Stream - 应用 Collector groupingBy 后将对象列表收集到一组字符串中

给定以下类OrderItem以及 s 的列表Order

@Getter
@AllArgsConstructor
@ToString
public class Order {
    String customerName;
    List<Item> items;
}

@Getter
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Item {
    long id;
    String name;
}
Run Code Online (Sandbox Code Playgroud)

我需要创建一个映射Map<String,Set<String>> itemsByCustomerName,其中键是客户名称以及属于该客户名称Order的所有名称的一组名称。Item

输入示例:

List<Order> orders = List.of(
        new Order("John", List.of(new Item(1, "A"), new Item(2, "B"), new Item(3, "C"))),
        new Order("Alex", List.of(new Item(1, "A"), new Item(8, "H"), new Item(11, "K"))),
        new Order("John", List.of(new Item(1, "A"), new Item(6, "F"), new Item(7, "G"))),
        new …
Run Code Online (Sandbox Code Playgroud)

java java-stream collectors groupingby

3
推荐指数
1
解决办法
631
查看次数

如何在 Java 8 中使用 flatMap() 之上的收集器 groupingBy() 按属性对对象进行分组

如何创建Map<String,List<Product>> 如下。这里,String(的keyMap ) 是categorya 的Product

一种产品可以属于多个类别,如下例所示。

我正在尝试使用以下代码,但无法进行下一步操作:

products.stream()
    .flatMap(product -> product.getCategories().stream())
    . // how should I progress from here?
Run Code Online (Sandbox Code Playgroud)

结果应如下所示:

{电子=[p1,p3,p4], 时尚=[p1,p2,p4], 厨房=[p1,p2,p3], abc1=[p2], xyz1=[p3],pqr1=[p4]}

Product p1 = new Product(123, Arrays.asList("electonics,fashion,kitchen".split(",")));
Product p2 = new Product(123, Arrays.asList("abc1,fashion,kitchen".split(",")));
Product p3 = new Product(123, Arrays.asList("electonics,xyz1,kitchen".split(",")));
Product p4 = new Product(123, Arrays.asList("electonics,fashion,pqr1".split(",")));
List<Product> products = Arrays.asList(p1, p2, p3, p4);
Run Code Online (Sandbox Code Playgroud)
class Product {

    int price;
    List<String> categories;

    public Product(int price) { …
Run Code Online (Sandbox Code Playgroud)

java hashmap java-stream collectors groupingby

3
推荐指数
2
解决办法
381
查看次数

Java 8 Stream - 使用Custom Collector时出现NullPointerException

我通过实现Collector接口并覆盖其方法来实现自定义收集器.Collector实现如下:

class MyCustomCollector implements Collector<Person, StringJoiner, String>{

    @Override
    public Supplier<StringJoiner> supplier() {
        // TODO Auto-generated method stub
        return () -> new StringJoiner("|");
    }

    @Override
    public BiConsumer<StringJoiner, Person> accumulator() {
        // TODO Auto-generated method stub
        return (joiner,person) -> joiner.add(person.name.toUpperCase());
    }

    @Override
    public BinaryOperator<StringJoiner> combiner() {
        // TODO Auto-generated method stub
        return (joiner1, joiner2) -> joiner1.merge(joiner2);
    }

    @Override
    public Function<StringJoiner, String> finisher() {
        // TODO Auto-generated method stub
        return StringJoiner::toString;
    }

    @Override
    public Set<java.util.stream.Collector.Characteristics> characteristics() {
        // TODO Auto-generated method stub
        return …
Run Code Online (Sandbox Code Playgroud)

java-8 java-stream collectors

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

使用收集器根据Java中的类将steam拆分为列表

以下代码是一个伪代码,表示我想要实现的目标:

Map<Class<?>, List<?>> map = Stream.of(1, "2").collect(Collectors.groupingBy(Object::getClass));
List<Integer> ints = map.get(Integer.class);
List<String> strings = map.get(String.class);
Run Code Online (Sandbox Code Playgroud)

以上是简化的代码.我想要的是我有一个输入列表,我想根据对象的类将它拆分成多个列表.

但是上面的代码没有编译,我想知道你怎么能解决它?

java java-stream collectors

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