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?
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));
Où 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.
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.
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
});
Vous faites toujours l'une des choses suivantes:
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?
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.
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), ...