2017-05-05 5 views
1

Je veux réécrire le code suivant Java 8 être Java 7 compatible:Comment peut-on réécrire le flux Java 8() en utilisant des modèles Java 7?

System.out.println("items: " + stringList.stream().collect(Collectors.joining(", "))); 

Une façon naïve est:

System.out.print("items: "); 
String joiner = ""; 
for (String item : stringList) { 
    System.out.print(joiner + item); 
    joiner = ", "; 
} 
System.out.println(); 

Quels sont les modèles alternatifs pour accomplir cette tâche? Par exemple, pourrait-on utiliser un modèle de commande en quelque sorte en passant print() encapsulé comme un objet?

+0

StringBuilder .... –

+1

Ou tout simplement jeter un oeil au code source du JDK 8 [StringJoiner] (http : //grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/StringJoiner.java) class et écrivez une version JDK 7 –

+1

Votre code est presque correct . Le seul changement que je ferais est de 'System.out.print'' joiner' et 'item' séparément, pour éviter la création de chaîne inutile. 'StringBuilder' est moins efficace ici, puisque vous devriez simplement mettre en mémoire tampon les caractères, créer une chaîne, écrire dans un autre tampon de caractères; au lieu de cela, écrivez directement dans ce tampon final (comme vous le faites déjà). –

Répondre

0
StringBuilder sb = new StringBuilder("items: "); 
for (String item : stringList) { 
    sb.append(item).append(", "); 
} 
if (!stringList.isEmpty()) { 
    sb.setLength(sb.length() - 2); 
} 
System.out.println(sb.toString()); 

Commentaires:

  1. Le StringBuilder est initialisées avec l'argument constructeur
  2. append retourne un StringBuilder afin que vous puissiez les enchaîner
  3. Les deux derniers caractères doivent être supprimés pour éviter de fuite " , "
  4. stringList peut être vide, supprimez uniquement la virgule de fin si ce n'est pas
  5. Ceci est probablement plus efficace car vous évitez beaucoup de création et de copie temporaires.
+1

Alternativement, on pourrait d'abord ajouter le séparateur de deux points, si '! Sb.isEmpty()' et ensuite toujours ajouter l'élément suivant. –

+0

Merci. J'ai édité mon article original pour supprimer la création de la chaîne en boucle car ce n'était pas la partie que je voulais attirer l'attention. Ma question est vraiment comment accomplir la tâche donnée en utilisant un modèle de conception alternative. Par exemple, un modèle de commande transmettant une fonction encapsulée en tant que variable. –

2

Si vous avez goyave sur le chemin de classe (et vous vraiment Devrais-OMI), qu'il a la même couramment de se joindre, mais compatible avec jdk-7 (évidemment, vous avez besoin d'une version de goyave qui est jdk -7 compatible):

String joined = Joiner.on(",").join(stringList); 
0

Presque la même chose, concaténation simplement éviter:

System.out.print("items: "); 
boolean first = true; 
for (String item : stringList) { 
    if (! first) 
     System.out.print(", "); 
    System.out.print(item); 
    first = false; 
} 
System.out.println(); 

note: la signification du booléen pourrait être inversée si on n'a pas besoin d'utiliser la négation, mais je préfère c'est wa y pour plus de lisibilité.

0

Notez que votre code Java 8 d'origine

System.out.println("items: " + stringList.stream().collect(Collectors.joining(", "))); 

peut être simplifié à

System.out.println("items: " + String.join(", ", stringList)); 

En Java 7, vous devez utiliser un StringBuilder pour faire la même chose efficace, mais vous pouvez encapsuler dans une classe d'utilité, similaire à StringJoiner de Java 8. L'utilisation d'une classe avec la même API permet de créer du code compatible Java 7 encore facile à adapter pour utiliser la version Java 8.

Cependant, il est peu probable que ce soit la performance la plus partie critique de votre demande, par conséquent, vous pouvez utiliser une approche pragmatique:

String s = stringList.toString(); 
System.out.append("items: ").append(s, 1, s.length()-1).println(); 

Cela ne fonctionne tout simplement pas imprimer le [ et ] de la chaîne représentation, résultant en la liste séparée par des virgules souhaitée. Bien que cette représentation de chaîne ne soit pas obligatoire, il serait difficile de trouver un exemple d'implémentation de collection utile qui n'adhère pas à cette convention (et vous sauriez si vous avez utilisé une telle classe).En ce qui concerne votre question mise à jour se référant à quelque chose comme "modèle de commande", eh bien, cela n'a rien à voir avec le code Stream de votre question, mais il existe déjà des abstractions, comme celle utilisée dans le code ci-dessus.

Vous pouvez créer une méthode comme

static <A extends Appendable> A join(A target, CharSequence sep, List<?> data) { 
    try { 
     CharSequence currSep = ""; 
     for(Object item: data) { 
      target.append(currSep).append(item.toString()); 
      currSep = sep; 
     } 
     return target; 
    } catch(IOException ex) { 
     throw new IllegalStateException(ex); 
    } 
} 

qui offre une certaine flexibilité, par exemple vous pouvez l'utiliser pour acquérir un String:

String s = join(new StringBuilder(), ", ", stringList).toString(); 
System.out.println("items: " + s); 

ou tout simplement imprimer:

join(System.out.append("items: "), ", ", stringList).println();