代码之家  ›  专栏  ›  技术社区  ›  orbfish

如何在比较连续列表元素的基础上将Java流缩减为布尔值

  •  1
  • orbfish  · 技术社区  · 5 年前

    作为一个重构练习,我尝试这样做:

        for (int i = 1; i < orderedList.size(); i++) {
            Object object1 = ordered.get(i - 1);
            Object object2 = ordered.get(i);
            if (isDifferent(object1, object2)) return true;
        }
    
        return false;
    

    转换成一个简单的Java函数语句。乍一看,我是按顺序处理列表中的元素,所以 reduce() 听起来很有前途,但是

    1. 它需要携带一个布尔值,这会丢失前面的元素;或者
    2. 带着列表的前一个元素,这意味着我需要把它放在某种包装对象中,或者 Optional 或者别的什么 List 作为包装器,为了跟踪我是否有区别。

    所以,我看到了使用reduce操作的方法,但是它比for循环原始的更复杂更难理解。

    谢谢你对这个思考练习的帮助。

    2 回复  |  直到 5 年前
        1
  •  2
  •   Jacob G.    5 年前

    因为你在索引2 List 对于for循环,可以将其替换为 IntStream IntStream#anyMatch :

    return IntStream.range(1, orderedList.size())
                    .anyMatch(i -> isDifferent(ordered.get(i - 1), ordered.get(i)));
    

    不过,我并没有真正看到这有多大的好处,所以保持它作为for循环可能更具可读性。

        2
  •  1
  •   HTNW    5 年前

    这里的基本操作称为“zipping”:给定两个流 A B s与组合算子 (A, B) -> C C s(截断到较短的输入流)。假设你有这样的功能

    <A, B, C> Stream<C> zip
     (Stream<? extends A> as, Stream<? extends B> bs,
      BiFunction<? super A, ? super B, ? extends C> combine);
    

    您可以将操作实现为

    zip(ordered.stream(), ordered.stream().skip(1), this::isDifferent).anyMatch(x -> x);
    // ordered: a b c d ... y z
    // skipped: b c d ... y z
    // zipped : (a, b) (b, c) (c, d) ... (y, z)
    

    zip 在标准库中。如果你用的是番石榴,你可以检查一下。 here's one . 或者,您可以自己实现它,并将其粘贴到某个实用程序类中,此时您可能希望这样做 check out this answer . 我将复制这里列出的代码(它似乎是从实际的Streams API的beta版本中抄袭过来的):

    public static<A, B, C> Stream<C> zip(Stream<? extends A> a,
                                         Stream<? extends B> b,
                                         BiFunction<? super A, ? super B, ? extends C> zipper) {
        Objects.requireNonNull(zipper);
        Spliterator<? extends A> aSpliterator = Objects.requireNonNull(a).spliterator();
        Spliterator<? extends B> bSpliterator = Objects.requireNonNull(b).spliterator();
    
        // Zipping looses DISTINCT and SORTED characteristics
        int characteristics = aSpliterator.characteristics() & bSpliterator.characteristics() &
                ~(Spliterator.DISTINCT | Spliterator.SORTED);
    
        long zipSize = ((characteristics & Spliterator.SIZED) != 0)
                ? Math.min(aSpliterator.getExactSizeIfKnown(), bSpliterator.getExactSizeIfKnown())
                : -1;
    
        Iterator<A> aIterator = Spliterators.iterator(aSpliterator);
        Iterator<B> bIterator = Spliterators.iterator(bSpliterator);
        Iterator<C> cIterator = new Iterator<C>() {
            @Override
            public boolean hasNext() {
                return aIterator.hasNext() && bIterator.hasNext();
            }
    
            @Override
            public C next() {
                return zipper.apply(aIterator.next(), bIterator.next());
            }
        };
    
        Spliterator<C> split = Spliterators.spliterator(cIterator, zipSize, characteristics);
        return (a.isParallel() || b.isParallel())
               ? StreamSupport.stream(split, true)
               : StreamSupport.stream(split, false);
    }
    
        3
  •  0
  •   umamahesh    5 年前

    return orderedList.stream.distinct().count() != 1; // assuming that you have equals and 
                                                      //  hashcode method overridden for 
                                                      // your object.