2016-04-23 42 views
6

Ho già letto il post relativo a this. Quando si tratta di operazioni con le corde, i flussi sembrano attrarre una grande quantità di cerimonie. Se si desidera analizzare una stringa come flusso di caratteri su cui si desidera eseguire alcune operazioni, è necessario convertirli in uno IntStream prima, mappare a Object, quindi trasmettere lo int a char, infine il numero di serie da char a String e quindi restituirlo.Gli stream Java 8 non sono pensati per essere utilizzati con caratteri e stringhe?

E la gente dice che la programmazione in stile imperativo ha una cerimonia in testa. Per favore correggimi se sto sbagliando completamente. La mia intenzione non è di prendere in giro ma di capire meglio i flussi di Java perché generalmente li apprezzo.

// Simple method which encrypts all chars in a string 
String input = "Hel!lo"; 

String result = input.chars()        // Need to convert into an IntStream 
     .mapToObj(e -> Character.toUpperCase((char) e))  // Need to map to Object (!) and then cast to char 
     .map(CryptoMath::encryptChar)      // Calling the encryption 
     .map(String::valueOf)        // Need to cast to String again... 
     .collect(joining(""));        // Finally done 

System.out.println(result); 
+1

Si può semplicemente considerare 'char' come un' int'. Ma questo problema è in realtà un retaggio dell'intero problema dei tipi primitivi di Java. –

+0

Beh, se lo faccio ho bisogno di cambiare ogni metodo con i parametri char da prendere invece, che è odore di codice secondo me. A quale problema si riferisce a primitive? Hai qualche link? – AdHominem

+1

Basta Google. Non puoi usare i generici con i primitivi. Dovevano scrivere lo stesso codice per 'Stream ', 'IntSteam' ** e **' LongStream'. Hanno scelto di non creare un 'CharStream'. Questa è un'ancora che trattiene il moderno Java; e non uno che può essere tagliato. –

risposta

3

Se è possibile operare su Unicode punti di codice al posto dei caratteri, diventa un po 'meno ingombrante di operare su char:

String input = "Hel!lo"; 

String result = input.codePoints() 
        .map(Character::toUpperCase) 
        .collect(StringBuilder::new, 
           StringBuilder::appendCodePoint, 
           StringBuilder::append) 
        .toString(); 

System.out.println(result); 

Non c'è boxe richiesta, nessuna conversione a stringa al punto di raccolta, e si hanno meno probabilità di essere inciampati da coppie surrogate nei dati di input. Una di quelle belle occasioni in cui è meno doloroso implementare qualcosa che si adatti a un insieme più ampio di input.

+1

-1 questo è un suggerimento dal post correlato, che l'OP aveva già letto e non ha trovato una risposta soddisfacente. Dovresti citare il suggerimento nell'altro post e spiegare perché esso fornisce una risposta per l'OP. –

+0

Se avessi notato quel commento nel post correlato, avrei potuto farlo, ma a mio discredito l'ho sfogliato e l'ho perso. A mio avviso, si trattava di un piccolo commento piuttosto che di una risposta e non forniva un esempio di codice che chiarisse quanto sarebbe stato più semplice da usare. Non si sa mai, impostarlo come sopra con un chiaro esempio potrebbe aver permesso all'OP di dire "in realtà, funzionerà per me", assumendo che diversamente da me aveva visto e scartato quel commento dal post collegato. Altrimenti, è perfettamente libero di non accettarlo come risposta. –

1

Con Eclipse Collections, è possibile integrare le parti mancanti nella libreria standard Java. Quanto segue funzionerà usando CharAdapter, supponendo CryptoMath.encryptChar() restituisce char.

String result = CharAdapter.adapt(input) 
     .collectChar(Character::toUpperCase) 
     .collectChar(CryptoMath::encryptChar) 
     .makeString(""); 

Nota: sono responsabile per le raccolte Eclipse.