2016-05-01 7 views
4

Ich möchte die Menge aller Wörter in einer Datei finden.Dieser Satz sollte sortiert werden. Ober- und Kleinschreibung spielt keine Rolle. Hier ist mein Ansatz:Stream von Strings ist nicht sortiert?

public static Set<String> setOfWords(String fileName) throws IOException { 

    Set<String> wordSet; 
    Stream<String> stream = java.nio.file.Files.lines(java.nio.file.Paths.get(fileName)); 

    wordSet = stream 
       .map(line -> line.split("[ .,;?!.:()]")) 
       .flatMap(Arrays::stream) 
       .sorted() 
       .map(String::toLowerCase) 
       .collect(Collectors.toSet()); 
    stream.close(); 
    return wordSet; 
} 

Testdatei:

Dies ist eine Datei mit fünf lines.It hat zwei Sätze, und die Word-Datei in mehreren Zeilen dieser Datei enthalten ist. Diese Datei kann zum Testen verwendet werden?

Beim Drucken des Satzes, erhalte ich die folgende Ausgabe:

Set of words: 
a 
be 
in 
sentences 
testing 
this 
for 
multiple 
is 
it 
used 
two 
the 
can 
with 
contained 
file 
and 
of 
has 
lines 
five 
word 

Kann jemand mir sagen, warum der Satz ist nicht sortiert in ihrer natürlichen Ordnung ist (für Streicher lexiographic)?

Vielen Dank im Voraus

+4

Ein Set nicht sortiert ist. Sie müssen dafür ein 'SortedSet' verwenden. – Tunaki

+0

Statt '.map (line -> line.split (" [.,;?!. :()] ")) .flatMap (Arrays :: stream)' können Sie '.map (Pattern.compile ("[.,;?!. :()]")) :: splitAsStream) '. So können Sie das Muster kompilieren nur einmal statt einmal von pro Zeile und vermeiden, dass die Schaffung eines Zwischen Array für jede Zeile ... – Holger

Antwort

5

Da die Bestellung ist Groß- und Kleinschreibung, sollten Sie Fall zu senken, vor dem Sortieren abzubilden.

Abgesehen davon, sollten Sie die Ausgabe in eine geordnete Sammlung wie eine List oder eine SortedSet Implementierung sammeln (obwohl, wenn Sie ein SortedSet verwenden es keine Notwendigkeit sorted() auszuführen ist, da die Set ohnehin sortiert werden).

A List Ausgang:

List<String> wordSet = stream 
      .map(line -> line.split("[ .,;?!.:()]")) 
      .flatMap(Arrays::stream) 
      .map(String::toLowerCase) 
      .sorted() 
      .collect(Collectors.toList()); 

EDIT:

Wie Hank kommentiert, wenn Sie Duplikate in der Ausgabe Collection beseitigen wollen, ein List nicht tun, so dass Sie haben, werde Sammeln Sie die Elemente in eine Implementierung.

A SortedSet Ausgang:

Set<String> wordSet = stream 
      .map(line -> line.split("[ .,;?!.:()]")) 
      .flatMap(Arrays::stream) 
      .map(String::toLowerCase) 
      .collect(Collectors.toCollection(TreeSet::new)); 
+3

danke ich es jetzt auf diese Weise gelöst und i funktioniert perfekt: SortedSet wordSet; \t \t Strom stream = java.nio.file.Files.lines (java.nio.file.Paths.get (Dateiname)); \t \t wordSet = stream \t \t \t \t \t .map (line -> line.split ("[,;.?!. :()]")) \t \t \t \t \t .flatMap (Arrays :: Strom) \t \t \t \t \t .map (String :: toLowerCase) \t \t \t \t \t .collect (Collectors.toCollection (TreeSet :: neu)); – Don

+1

'TreeSet' verwendet einen Heap-Sortieralgorithmus. Wenn Sie stattdessen den Algorithmus aus dem 'Stream' verwenden wollen, verwenden Sie' .sorted() 'und ein' LinkedHashSet' (was geordnet aber nicht sortiert ist) – RAnders00

+1

Diese Lösung erlaubt Duplikate, die im Problem nicht ausgeschlossen waren, aber wurde angedeutet, denke ich. –

7

Sie können eine sortierte Sammlung wie ein String.CASE_INSENSITIVE_ORDER als Comparator mit TreeSet verwenden

Set<String> set = stream 
      .map(line -> line.split("[ .,;?!.:()]")) 
      .flatMap(Arrays::stream) 
      .collect(Collectors.toCollection(()-> new TreeSet<>(String.CASE_INSENSITIVE_ORDER))); 

Oder Sie können die Elemente mit einem Groß- und Kleinschreibung Komparator sortieren und sammeln in eine Sammlung, die die Reihenfolge der Anzeigen verwaltet.

List<String> list = stream 
      .map(line -> line.split("[ .,;?!.:()]")) 
      .flatMap(Arrays::stream) 
      .sorted(String::compareToIgnoreCase) 
      .distinct() 
      .collect(Collectors.toList()); 
+2

Im zweiten Beispiel könnten Sie eine 'distinct()' hinzufügen, um Duplikate aus der Liste zu entfernen. – assylias

+1

Beachten Sie, dass der Komparator, den Sie mit 'TreeSet' (' String.CASE_INSENSITIVE_ORDER') verwenden, auch mit '.sorted (...)' auf einem 'Stream' arbeitet. Es gibt keine Notwendigkeit, zu der Methodenreferenz 'String :: compareToIgnoreCase' zu ​​wechseln, wenn mit Streams gearbeitet wird ... – Holger

+0

@Holger sicher, ich wollte verschiedene Wege zeigen, vielleicht vermeiden die OP oder zukünftige Besucher toLowerCase für solch eine Aufgabe :) –

Verwandte Themen