J'ai une seule chaîne de format:
row1col1 row1col2
row2col1 row2col2
row3col1 row3col2
etc...
Je veux extraire chaque élément et créer un tableau d'objets avec des propriétés comme ceci:
new MyObject(row1col1, row1col2);
Je suis nouveau sur Java 8 et Streams et je voudrais savoir comment puis-je y parvenir sans boucles.
Normalement, j'utiliserais une String.split('\n')
pour accumuler les lignes dans un tableau de String
Et puis une boucle où, pour chaque ligne, je diviserais à nouveau sur le séparateur d'espace et avec le tableau résultant des deux éléments (row1col1 row1col2
) Construirais mon objet, jusqu'à ce qu'il n'y ait plus de lignes à traiter.
Comme ça:
String sausage = "row1col1 row1col2\nrow2col1 row2col2\nrow3col1 row3col2";
String[] rows = sausage.split("\n");
for (String row : rows) {
String[] objectData = u.split("\\s+");
MyObject myObject = new MyObject(objectData[0], objectData[1]);
myObjectList.add(myObject);
}
Quelqu'un peut-il m'expliquer comment réaliser la même chose avec les flux et quel est le mécanisme qui me permet de le faire?
Est-ce même une façon de penser valable lors de l'augmentation du nombre d'éléments parce que de tous les exemples que j'ai vus, les flux se concentrent sur le filtrage, la collecte ou généralement donné un ensemble d'éléments récupérer un ensemble mineur en appliquant certains critères.
Un moyen simple serait de créer un Pattern
avec le séparateur de ligne et de diviser l'entrée String
en Stream
. Ensuite, chaque ligne est séparée par un espace (ne gardant que 2 parties) et mappée sur un MyObject
. Enfin, un tableau est construit avec le résultat.
public static void main(String[] args) {
String str = "row1col1 row2col2\r\nrow2col1 row2col2\r\nrow3col1 row3col2";
MyObject[] array =
Pattern.compile(System.lineSeparator(), Pattern.LITERAL)
.splitAsStream(str)
.map(s -> s.split("\\s+", 2))
.map(a -> new MyObject(a[0], a[1]))
.toArray(MyObject[]::new);
System.out.println(Arrays.toString(array));
}
L'utilisation de splitAsStream
peut être avantageuse par rapport à Stream.of(...)
si l'entrée String
est longue.
J'ai supposé dans le code que le séparateur de ligne du String
était le séparateur de ligne par défaut (System.lineSeparator()
) du système d'exploitation, mais vous pouvez le changer s'il ne l'est pas.
Au lieu de cela, si vous lisez un fichier, vous pouvez utiliser Files.lines()
pour obtenir un Stream
de toutes les lignes du fichier:
MyObject[] array = Files.lines(path)
.map(s -> s.split("\\s+", 2))
.map(a -> new MyObject(a[0], a[1]))
.toArray(MyObject[]::new);
System.out.println(Arrays.toString(array));
Vous pouvez générer un Stream
de String
s qui représente une seule instance de MyObject
et les transformer chacun en votre instance de MyObject
(en les séparant d'abord et puis construction d'une instance MyObject
):
List<MyObject> list =
Stream.of(inputString.split("\n"))
.map (s -> s.split(" "))
.filter (arr -> arr.length == 2) // this validation may not be necessary
// if you are sure each line contains 2 tokens
.map (arr -> new MyObject(arr[0],arr[1]))
.collect(Collectors.toList());