2016-10-19 3 views
0

Diese Frage ist nur zum Spaß.Gib die N letzten Elemente in Java Streams zurück

Ich habe diese Methode:

private static String getBaseDomain(String fullDomain) { 
    // we take the base domain from the usual xxx.yyy.basedomain.tld: we 
    // want only the last 2 elements: basedomain.tld 
    List<String> elements = Arrays.asList(fullDomain.split("\\.")); 
    if(elements.size() > 2){ 
     elements = elements.subList(elements.size()-2, elements.size()); 
    } 
    return String.join(".", elements); 
} 

Und ich frage mich, wie das gleiche Ergebnis zu erhalten, den Java-Stream-API (eigentlich ich frage mich, welche Methode wäre die ressourceneffiziente).

Ich kann nicht verstehen, wie man nur die letzten zwei Elemente aus einem Stream zu bekommen: limit(2) gibt mir die erste zwei, und für skip(XXX) ich weiß nicht, wie die Größe des Stroms „inline“ zu extrahieren .

Können Sie mir sagen, wie Sie es tun würden?

+0

Ich empfehle, eine Art von Falte mit Warteschlange als Akkumulator zu verwenden und Element zu entfernen, wenn es eine bestimmte Größe erreicht. – talex

Antwort

5

könnten Sie skip verwenden:

elements.stream().skip(elements.size() - 2) 

Vom API:

Gibt einen Strom der übrigen Elemente dieses Stroms aus, nachdem sie die ersten n Elemente des Stroms zu verwerfen. Wenn dieser Stream weniger als n Elemente enthält, wird ein leerer Stream zurückgegeben.

Wahrscheinlich nutzlos Beispiel:

// a list made of a, b, c and d 
List<String> l = Arrays.asList("a", "b", "c", "d"); 

// prints c and d 
l.stream().skip(l.size() - 2).forEach(System.out::println); 

Wahrscheinlich nutzlos Anmerkung:

Wie durch ein paar erwähnt, funktioniert dies nur, wenn Sie haben eine Größe, mit zu arbeiten, das heißt, wenn Sie streamen aus einer Sammlung.

Notieren Nicolas, ein Stream hat keine Größe.

+0

Wenn 'elements'' Stream' ist, können Sie das nicht tun. Weil du es zweimal verwendest. – talex

+0

@talex oh, ja typo - fixed - elements ist hier eine 'List'. – Mena

+0

Bitte beachten Sie, dass dies nur mit einer 'Sammlung' funktioniert, nicht mit einem' Stream', da ein 'Stream' keine Größe –

1

Wenn elements ein Strom ist, können Sie eine benutzerdefinierte Collector schreiben gerade die letzten K Elemente zu halten (es auch ein Sammler wie dies bereits sein kann):

List<?> lastK = ints.stream().collect(
    Collector.of(
     LinkedList::new, 
     (listA, el) -> { 
      listA.add(el); 
      if (listA.size() > K) { 
       listA.remove(0); 
      } 
     }, 
     (listA, listB) -> { 
      while (listB.size() < K && !listA.isEmpty()) { 
       listB.addFirst(listA.removeLast()); 
      } 
      return listB; 
     })); 
+2

Man könnte sogar ein 'ArrayDeque' anstelle von' LinkedList' verwenden, um die Leistung der Akkumulations- und Zusammenführungsfunktion zu verbessern, aber auf Kosten eines 'ArrayList :: new'Finishers wenn Der Ergebnistyp muss eine 'List' sein. – Holger

1

Wenn es eine indizierte Sammlung konnte man verwenden

IntStream.range(elements.size() - 2, elements.size()).mapToObj(elements::get).forEach(System.out::print); 
2

Sie könnten ein bisschen inlining Ihrer ursprünglichen Ansatz tun, was ich denke, es ist schön verkürzt, und Sie haben nicht einmal einen Stream verwenden müssen:

String[] a = fullDomain.split("\\."); 
    return String.join(".", Arrays.asList(a) 
            .subList(Math.max(0, a.length-2), a.length)); 

Wenn Sie wirklich einen Stream verwenden möchten, können Sie die Array-subrange Stromquelle verwenden können:

String[] a = fullDomain.split("\\."); 
    return Arrays.stream(a, Math.max(0, a.length-2), a.length) 
       .collect(Collectors.joining(".")); 

Wenn alles, was Sie haben ein Strom ist, dessen Größe man im Voraus nicht haben, ich d nur die Elemente in eine ArrayDeque Dump:

final int N = 2; 
    Stream<String> str = ... ; 

    Deque<String> deque = new ArrayDeque<>(N); 
    str.forEachOrdered(s -> { 
     if (deque.size() == N) deque.removeFirst(); 
     deque.addLast(s); 
    }); 
    return String.join(".", deque); 

natürlich, das als das Schreiben eines Kollektors nicht so allgemein ist, aber für einfache Fälle ist es wahrscheinlich gut.

Verwandte Themen