Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java streams: easiest way to find adjacent value match

How would it be possible to convert this iterative block of code to streams?

Integer prev = -1;
boolean adjacentPair = false;

for(Integer num : numberList) {
    if (num.equals(prev)) {
        adjacentNumberSame = true;
        break;
    }
    prev = num;
}
return adjacentNumberSame 
like image 545
tjago Avatar asked Jan 24 '26 13:01

tjago


1 Answers

This is one (not so great) way to do it:

IntStream.range(1, numberList.size())
         .anyMatch(i -> numberList.get(i).equals(numberList.get(i-1)));

If your numberList is an ArrayList or something similar its complexity is acceptable. If not, you'd better use iterator. Like so:

var Iter = list.stream().iterator();
var res = list.stream()
              .skip(1)
              .map(v -> v.equals(Iter.next()) )
              .anyMatch(v -> v)
              ;

More elegant ways require some third-party libraries with a zip function. With zip it can look like:

var res = zip(
              list.stream().skip(1),
              list.stream(),
              (a, b) -> a.equals(b)
          ).anyMatch(x->x);

Or you can write your own zip. Something like this:

public static <A,B,C> Stream<C> zip(Stream<A> listA, Stream<B> listB, BiFunction<A,B,C> zipper){
    var iB = listB.iterator();
    return listA.filter( a -> iB.hasNext())
                .map( a -> zipper.apply(a, iB.next()) );
}

PS. I would not recommend reduce as it used in @vbezhenar's answer. Because it will not shortcircuit, as you can see here https://repl.it/repls/DisastrousWideRevisioncontrol (look for exception)

like image 193
x00 Avatar answered Jan 27 '26 02:01

x00



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!