Operazioni su stringhe con Java Streams

1. Panoramica

Java 8 ha introdotto una nuova API Stream che ci consente di elaborare i dati in modo dichiarativo.

In questo rapido articolo, impareremo come utilizzare l' API Stream per dividere una stringa separata da virgole in un elenco di stringhe e come unire una matrice di stringhe in una stringa separata da virgole .

Vedremo anche come convertire un array di stringhe da mappare utilizzando Stream API.

Quasi sempre affrontiamo situazioni in cui dobbiamo iterare alcune collezioni Java e filtrare la collezione in base a una logica di filtraggio. In un approccio tradizionale per questo tipo di situazione, utilizzeremmo molti cicli e operazioni if-else per ottenere il risultato desiderato.

Se vuoi saperne di più sull'API Stream , controlla questo articolo.

2. Unione di stringhe con l' API Stream

Usiamo l' API Stream per creare una funzione che unirebbe un array String in una String separata da virgole :

public static String join(String[] arrayOfString){ return Arrays.asList(arrayOfString) .stream() //.map(...) .collect(Collectors.joining(",")); }

Punti da notare qui:

  • La funzione stream () converte qualsiasi Collection in un flusso di dati
  • La funzione map () viene utilizzata per elaborare i dati
  • C'è anche un'altra funzione, chiamata filter () , in cui possiamo includere criteri di filtraggio

Ci possono essere scenari in cui potremmo voler unire una stringa con alcuni prefissi e suffissi fissi. Con l' API Stream possiamo farlo nel modo seguente:

public static String joinWithPrefixPostfix(String[] arrayOfString){ return Arrays.asList(arrayOfString) .stream() //.map(...) .collect(Collectors.joining(",","[","]")); }

Come possiamo vedere nel metodo Collectors.joining () , stiamo dichiarando il nostro prefisso come '[' e postfisso come ']' ; quindi la stringa generata verrà creata con il formato [… ..] dichiarato .

3. Divisione di stringhe con Stream API

Ora, creiamo una funzione, che dividerebbe una stringa separata da virgole in un elenco di stringhe utilizzando l' API Stream :

public static List split(String str){ return Stream.of(str.split(",")) .map (elem -> new String(elem)) .collect(Collectors.toList()); }

È anche possibile convertire direttamente una stringa in un elenco di caratteri utilizzando l' API Stream :

public static List splitToListOfChar(String str) { return str.chars() .mapToObj(item -> (char) item) .collect(Collectors.toList()); }

Un fatto interessante da notare qui è che il metodo chars () converte la stringa in un flusso di Integer dove ogni valore Integer denota il valore ASCII di ogni sequenza di Char . Ecco perché dobbiamo tipizzare esplicitamente l'oggetto mapper nel metodo mapToObj () .

4. String Array Mappa Con flusso API

Possiamo anche convertire un array String in mapping utilizzando split e Collectors.toMap , a condizione che ogni elemento dell'array contenga un'entità valore-chiave concatenata da un separatore:

public static Map arrayToMap(String[] arrayOfString) { return Arrays.asList(arrayOfString) .stream() .map(str -> str.split(":")) .collect(toMap(str -> str[0], str -> str[1])); }

Qui, ":" è il separatore di valori-chiave per tutti gli elementi nell'array di stringhe.

Ricorda che per evitare errori di compilazione, dobbiamo assicurarci che il codice sia compilato utilizzando Java 1.8 . Per fare ciò, dobbiamo aggiungere il seguente plugin nel pom.xml :

   org.apache.maven.plugins maven-compiler-plugin 3.3  1.8 1.8    

5. Test

Dato che abbiamo finito di creare le funzioni, creiamo casi di test per verificare il risultato.

Innanzitutto, testiamo il nostro semplice metodo di unione:

@Test public void givenArray_transformedToStream_convertToString() { String[] programmingLanguages = {"java", "python", "nodejs", "ruby"}; String expectation = "java,python,nodejs,ruby"; String result = JoinerSplitter.join(programmingLanguages); assertEquals(result, expectation); }

Successivamente, creiamo un altro per testare la nostra semplice funzionalità di divisione:

@Test public void givenString_transformedToStream_convertToList() { String programmingLanguages = "java,python,nodejs,ruby"; List expectation = new ArrayList(); expectation.add("java"); expectation.add("python"); expectation.add("nodejs"); expectation.add("ruby"); List result = JoinerSplitter.split(programmingLanguages); assertEquals(result, expectation); }

Infine, testiamo il nostro array String per mappare la funzionalità:

@Test public void givenStringArray_transformedToStream_convertToMap() { String[] programming_languages = new String[] {"language:java","os:linux","editor:emacs"}; Map expectation=new HashMap(); expectation.put("language", "java"); expectation.put("os", "linux"); expectation.put("editor", "emacs"); Map result = JoinerSplitter.arrayToMap(programming_languages); assertEquals(result, expectation); }

Allo stesso modo, dobbiamo creare il resto dei casi di test.

6. Conclusione

Stream API ci fornisce sofisticate tecniche di elaborazione dei dati. Questo nuovo modo di scrivere codice è molto efficiente in termini di gestione della memoria heap in un ambiente multi-thread.

Come sempre, il codice sorgente completo è disponibile su Github.