Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip)

前端 未结 14 1387
旧巷少年郎
旧巷少年郎 2020-11-21 23:24

In JDK 8 with lambda b93 there was a class java.util.stream.Streams.zip in b93 which could be used to zip streams (this is illustrated in the tutorial Exploring Java8 Lambda

相关标签:
14条回答
  • 2020-11-21 23:52

    Since I can't conceive any use of zipping on collections other than indexed ones (Lists) and I am a big fan of simplicity, this would be my solution:

    <A,B,C>  Stream<C> zipped(List<A> lista, List<B> listb, BiFunction<A,B,C> zipper){
         int shortestLength = Math.min(lista.size(),listb.size());
         return IntStream.range(0,shortestLength).mapToObj( i -> {
              return zipper.apply(lista.get(i), listb.get(i));
         });        
    }
    
    0 讨论(0)
  • 2020-11-21 23:53

    AOL's cyclops-react, to which I contribute, also provides zipping functionality, both via an extended Stream implementation, that also implements the reactive-streams interface ReactiveSeq, and via StreamUtils that offers much of the same functionality via static methods to standard Java Streams.

     List<Tuple2<Integer,Integer>> list =  ReactiveSeq.of(1,2,3,4,5,6)
                                                      .zip(Stream.of(100,200,300,400));
    
    
      List<Tuple2<Integer,Integer>> list = StreamUtils.zip(Stream.of(1,2,3,4,5,6),
                                                      Stream.of(100,200,300,400));
    

    It also offers more generalized Applicative based zipping. E.g.

       ReactiveSeq.of("a","b","c")
                  .ap3(this::concat)
                  .ap(of("1","2","3"))
                  .ap(of(".","?","!"))
                  .toList();
    
       //List("a1.","b2?","c3!");
    
       private String concat(String a, String b, String c){
        return a+b+c;
       }
    

    And even the ability to pair every item in one stream with every item in another

       ReactiveSeq.of("a","b","c")
                  .forEach2(str->Stream.of(str+"!","2"), a->b->a+"_"+b);
    
       //ReactiveSeq("a_a!","a_2","b_b!","b_2","c_c!","c2")
    
    0 讨论(0)
  • 2020-11-21 23:53

    If anyone needs this yet, there is StreamEx.zipWith function in streamex library:

    StreamEx<String> givenNames = StreamEx.of("Leo", "Fyodor")
    StreamEx<String> familyNames = StreamEx.of("Tolstoy", "Dostoevsky")
    StreamEx<String> fullNames = givenNames.zipWith(familyNames, (gn, fn) -> gn + " " + fn);
    
    fullNames.forEach(System.out::println);  // prints: "Leo Tolstoy\nFyodor Dostoevsky\n"
    
    0 讨论(0)
  • 2020-11-21 23:54

    zip is one of the functions provided by the protonpack library.

    Stream<String> streamA = Stream.of("A", "B", "C");
    Stream<String> streamB  = Stream.of("Apple", "Banana", "Carrot", "Doughnut");
    
    List<String> zipped = StreamUtils.zip(streamA,
                                          streamB,
                                          (a, b) -> a + " is for " + b)
                                     .collect(Collectors.toList());
    
    assertThat(zipped,
               contains("A is for Apple", "B is for Banana", "C is for Carrot"));
    
    0 讨论(0)
  • 2020-11-21 23:57

    Zipping two streams using JDK8 with lambda (gist).

    public static <A, B, C> Stream<C> zip(Stream<A> streamA, Stream<B> streamB, BiFunction<A, B, C> zipper) {
        final Iterator<A> iteratorA = streamA.iterator();
        final Iterator<B> iteratorB = streamB.iterator();
        final Iterator<C> iteratorC = new Iterator<C>() {
            @Override
            public boolean hasNext() {
                return iteratorA.hasNext() && iteratorB.hasNext();
            }
    
            @Override
            public C next() {
                return zipper.apply(iteratorA.next(), iteratorB.next());
            }
        };
        final boolean parallel = streamA.isParallel() || streamB.isParallel();
        return iteratorToFiniteStream(iteratorC, parallel);
    }
    
    public static <T> Stream<T> iteratorToFiniteStream(Iterator<T> iterator, boolean parallel) {
        final Iterable<T> iterable = () -> iterator;
        return StreamSupport.stream(iterable.spliterator(), parallel);
    }
    
    0 讨论(0)
  • 2020-11-21 23:57

    The methods of the class you mentioned have been moved to the Stream interface itself in favor to the default methods. But it seems that the zip method has been removed. Maybe because it is not clear what the default behavior for different sized streams should be. But implementing the desired behavior is straight-forward:

    static <T> boolean every(
      Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred) {
        Iterator<T> it=c2.iterator();
        return c1.stream().allMatch(x->!it.hasNext()||pred.test(x, it.next()));
    }
    static <T> T find(Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred) {
        Iterator<T> it=c2.iterator();
        return c1.stream().filter(x->it.hasNext()&&pred.test(x, it.next()))
          .findFirst().orElse(null);
    }
    
    0 讨论(0)
提交回复
热议问题