简体   繁体   English

Java 8 Lambda-多次使用流

[英]java 8 lambda - use stream multiple times

Is it possible to avoid creating stream inside current stream from the same collection like in below example to collect some data (listOfA is used two times to create stream) ? 是否有可能避免从同一集合中的当前流内部创建流,如以下示例中那样收集一些数据(listOfA被使用两次来创建流)?

List<A> listOfA = Arrays.asList(new A(1L, "A1", "V1"), new A(2L, "A2", "V1"), new A(1L, "A1", "V2"));

List<B> listOfB = listOfA.stream().map(r -> new B(r.getId(), r.getName(),
            listOfA.stream().filter(r2 -> r.getId().equals(r2.getId())).map(A::getVal).collect(toSet())
    )).distinct().collect(toList());

class A {
     private final Long id;
     private final String name;
     private final String val;

     A(Long id, String name, String val) //constructor
     //getters

}

class B {
     private final Long id;
     private final String name;
     private final Set<String> values;

     B(Long id, String name, Set<String> values) //constructor
     //getters


     @Override
     public boolean equals(Object o) {
          ...
          return id.equals(a.id);
     }
     //hashCode
 }

The final result should be a list of 2 objects: 最终结果应该是2个对象的列表:

B{id=1, name='A1', values=[V1, V2]} B {id = 1,名称=“ A1”,值= [V1,V2]}

B{id=2, name='A2', values=[V1] B {id = 2,名称='A2',值= [V1]

Thanks in advance! 提前致谢!

I'm not sure what you question aims at. 我不确定您要问的目标是什么。 If the question is what the minimal changes are that are necessary in order to avoid re-creating the stream, then I have to answer: I don't know. 如果问题是为了避免重新创建流而需要进行最小的更改,那么我必须回答:我不知道。 However, it seems like your approach is overly complicated. 但是,您的方法似乎过于复杂。 The chain of map , collect , filter , distinct and collect that is built there is really hard to understand. mapcollectfilterdistinctcollect是内置有实在令人费解。

After a short rant... 经过短暂的咆哮...

Maybe my fear that future Java programs will all look like this, and thus become completely unmaintainable is not justified. 也许我担心将来的Java程序都会看起来像这样,因此变得完全无法维护是没有道理的。 Maybe one just has "to get used to" this programming style. 也许只是“习惯”了这种编程风格。 Maybe there's a short period when people are too eager with using the new language features, and it will come back to a "normal" style (and a "healthy" level of functional elements) sooner or later. 可能会有一个短暂的时期,人们过于渴望使用新的语言功能,并且迟早会恢复为“正常”风格(以及功能元素的“健康”水平)。 But I, personally, think that a method like createBsByMergingTheValuesOfAs() would be sufficient and appropriate here. 但是我个人认为,像createBsByMergingTheValuesOfAs()这样的方法在这里就足够了。

... I'd like to suggest using a dedicated Collector , which already offers much of the infrastructure for mutable reduction that you seem to be emulating with this chain of operations: ...我想建议使用一个专用的Collector ,它已经提供了许多可变可变的基础结构,您似乎正在使用此操作链进行模拟:

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class StreamCollectTest
{
    public static void main(String[] args)
    {
        List<A> listOfA = Arrays.asList(
            new A(1L, "A1", "V1"), 
            new A(2L, "A2", "V1"), 
            new A(1L, "A1", "V2"));

        Map<Long, B> result = listOfA.stream().collect(
            Collectors.toConcurrentMap(

                // The "id" will be the key of the map
                a -> a.getId(), 

                // The initial value stored for each key will be a "B"
                // whose set of values contains only the element of 
                // the corresponding "A"
                a -> new B(a.getId(), a.getName(), 
                    new LinkedHashSet<String>(Collections.singleton(a.getVal()))),

                // Two "B"s with the same key will be merged by adding
                // all values from the second "B" to that of the first
                (b0,b1) -> { b0.values.addAll(b1.values); return b0; }));

        System.out.println(result);
    }

    static class A
    {
        private final Long id;
        private final String name;
        private final String val;

        A(Long id, String name, String val)
        {
            this.id = id;
            this.name = name;
            this.val = val;
        }

        public Long getId()
        {
            return id;
        }

        public String getName()
        {
            return name;
        }

        public String getVal()
        {
            return val;
        }
    }

    static class B
    {
        private final Long id;
        private final String name;
        private final Set<String> values;

        B(Long id, String name, Set<String> values)
        {
            this.id = id;
            this.name = name;
            this.values = values;
        }

        @Override
        public String toString()
        {
            return id+","+name+","+values;
        }
    }
}

It prints 它打印

{1=1,A1,[V1, V2], 2=2,A2,[V1]}

So the values() of the resulting map should be exactly what you are looking for. 因此,结果图的values()应该正是您要寻找的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM