web-dev-qa-db-fra.com

Java 8 Stream: Comment comparer l’élément actuel avec l’élément suivant?

Comment obtenir le prochain élément d'une List en utilisant Java 8 Streams? 

Si je parcours une List, je souhaite comparer l'élément courant avec l'élément suivant de la liste. 

Est-ce faisable d'utiliser Java 8 Stream?

14
bhupen

My free StreamEx library vous permet de traiter les paires d'éléments de flux à l'aide d'une opération supplémentaire pairMap intermediate. Comme ça:

StreamEx.of(input).pairMap((current, next) -> doSomethingWith(current, next));

input est un Collection, un tableau ou Stream. Par exemple, vous pouvez facilement vérifier si l’entrée est triée:

boolean isSorted = StreamEx.of(input)
                           .pairMap((current, next) -> next.compareTo(current))
                           .allMatch(cmp -> cmp >= 0);

Il y a aussi forPairs opération de terminal qui est un analogique forEach pour toutes les paires d'éléments d'entrée:

StreamEx.of(input).forPairs((current, next) -> doSomethingWith(current, next));

Ces fonctionnalités fonctionnent parfaitement avec toutes les sources de flux (accès aléatoire ou non) et prennent totalement en charge les flux parallèles.

13
Tagir Valeev

Une solution consiste à générer une IntStream des index et à extraire les éléments List par leur index. Ceci n’est efficace que si la List prend en charge l’accès aléatoire (c’est-à-dire si votre List est une LinkedList, ce serait une mauvaise idée, car list.get(i) ne prend pas de temps constant).

Par exemple :

IntStream.range(0,list.size()-1).forEach(i -> {
    doSomething(list.get(i),list.get(i+1));
});

Une autre méthode consiste à stocker le dernier élément d'un tableau:

List<Element> list = ...
Element[] arr = new Element[1];
list.stream().forEach(e -> {
    if (arr[0] != null)
        doSomething(arr[0],e); 
    arr[0]=e;
});

Cela ne fonctionnera que pour les flux séquentiels.

10
Eran

Stream.reduce pourrait être utilisé, en fonction de l'objectif. Comme vous l'avez dit, vous souhaitez comparer des éléments consécutifs, le texte suivant indique "Same 3"

Stream.of(1,2,3,3).reduce((a,b)->{
    if(a==b) System.out.println("Same "+a);
    return b; // will be "a" for next reduction
});
1
Marc Dzaebel

Vous faites toujours l'une des choses suivantes:

  1. Convertissez votre flux en un flux d'éléments contenant "l'historique" des derniers éléments du flux
  2. Traitez votre flux de manière à ce que l'élément actuellement traité soit considéré comme l'élément "suivant" et que l'élément précédemment traité soit considéré comme un élément "actuel".

Les implémentations des deux solutions peuvent être vues dans ce fil de discussion: Est-il possible d’obtenir le prochain élément dans le Stream?

0
walkeros

Je devais faire la même chose et comparer les différences entre les éléments d'un flux (à l'origine un tableau) . J'ai donc utilisé une méthode en tant que paramètre de UnaryOperator que .map () attend comme suit ... et cela a fonctionné pour moi sans gizmo spécial:

import Java.util.Arrays;

class streamDiffUtil {
    public static void main(String[] args) {
        int[] elements = {1,2,5};
        int result = Arrays.stream(elements)
                .map(value -> calcMaxDiff(value, elements))
                .max()
                .getAsInt();
        System.out.println(result);
    }

    private static int calcMaxDiff(int j, int[] elements) {
        return Arrays.stream(elements)
                .map(value -> Math.abs(j-value))
                .max().getAsInt();
    }
}

Ce qui serait bien à Nice est de savoir comment la méthode calcMaxDiff équivaut à un UnaryIntOperator dans la signature .map. C'est un peu au-delà de moi ... Espérons que cela vous aide.

0
Beezer

Si vous avez une liste d'entiers par exemple et que vous voulez vérifier si elles sont triées par ordre croissant, vous pouvez procéder comme suit:

@Test
public void test_listIsSorted() {

    // create integer list for testing purposes: 0,1,2,3, .., 10
    List<Integer> integerList = IntStream.range(0, 10)
            .boxed()
            .collect(Collectors.toList());

    // stream list and compare item n with n+1
    integerList.stream()
            .reduce((integer1, integer2) -> {
                assert integer1 < integer2 : "ordering must be ascending";
                // return second value (which will be processed as "integer1" in the next iteration
                return integer2;
            });

}

Ceci comparera des paires comme: (0,1), (1,2), ...

0
Georg Moser