2015-09-19 9 views
11

Pisząc aplikacje w Javie, istnieje wiele przypadków użycia dla java.util.Collection. Od java.util.stream.Stream został wprowadzony z Java 8, natknąłem się na kilka przypadków użycia, gdzie trudno jest zdecydować, co używać.Decyzja między używaniem strumienia lub pętli

Na przykład: Zamierzasz napisać kilka metod-metod.

public static List<?> filterHashToList(int hash, Collection<?> toFilter) { 
    return toFilter.stream() 
     .filter((Object o) -> hash == o.hashCode()) 
     .collect(Collectors.toCollection(LinkedList::new)); 
} 

co pisać to tak:

public static List<?> filterHashToList(int hash, Collection<?> toFilter) { 
    List<Object> result = new LinkedList<>(); 

    for(Object o : toFilter) { 
     if(hash == o.hashCode()) { 
      result.add(o); 
     } 
    } 

    return result; 
} 

Obie metody będzie produkować ten sam rezultat. java.util.stream.Stream i java.util.stream.Collector są interfejsami, więc implementacja może się różnić, jeśli używam niestandardowych strumieni i kolektorów.

Wydaje mi się, że istnieje wiele implementacji tam, wykorzystujących starą fashoined pętlę.

Czy możliwe jest udzielenie odpowiedzi na pytanie, z czego korzystać, przesyłać strumieniowo lub w pętli? A jeśli tak, czy wszystkie implementacje muszą być aktualizowane w razie potrzeby?

A może powinienem podać oba sposoby, wdrażając metody util? Czy powinienem również podać mthed, zwracając strumień po procesie filtrowania, abyś mógł z nim pracować również w razie potrzeby?

+0

Możesz mieć naprawdę łatwy paralelizm ze strumieniami, są one bardziej kompaktowe (niektóre powiedzą "bardziej czytelne") i mają dodatkowe zalety, jeśli twoje strumienie są rzeczywistymi "strumieniami" (coś płynie, dynamicznie - nie na podstawie naprawiona kolekcja jak tutaj). Ale w twoim przypadku myślę, że możesz pójść w obie strony. – mastov

+0

Czy możemy to skrócić do: Preferujemy strumienie, ale w łatwych w użyciu przypadkach oba są w porządku? – narranoid

+3

Chciałbym użyć dwóch prostych zasad: 1. jeśli nie jest zepsuty, nie naprawiaj tego. 2. użyj tego, co uważasz za najbardziej czytelne i możliwe do utrzymania. To powiedziawszy, twoje dwa przykłady nie zwracają tego samego: jeden zwraca ArrayList, a drugi zwraca link Linked. –

Odpowiedz

5

Należy zauważyć, że w implementacji trzymać się specyficzne wynikające Collection Typ LinkedList który zazwyczaj ma bardzo słabe wyniki w porównaniu do ArrayList. Co jeśli użytkownik twojej metody chce użyć listy wynikowej w sposób losowy? Prawdopodobnie użytkownik tej metody potrzebuje tablicy, ponieważ powinna ona zostać przekazana do innej metody API, która akceptuje tablicę. Czasami użytkownik musi tylko wiedzieć, ile obiektów z danym hashCode jest obecnych w zbiorze wejściowym, więc nie ma potrzeby tworzenia w ogóle listy wynikowej. Java-8 sposobem jest powrót strumieni z metod, a nie zbiorów i pozwól rozmówcy zdecydować, jak je zbierać:

public static <T> Stream<T> filterHashToList(int hash, Collection<T> toFilter) { 
    return toFilter.stream() 
     .filter(o -> hash == o.hashCode()); 
} 

i używać go:

filterHashToList(42, input).count(); 

Albo

filterHashToList(42, input).collect(toCollection(ArrayList::new)); 

Albo

filterHashToList(42, input).toArray(); 

To wa y metoda staje się bardzo prosta, więc prawdopodobnie nie potrzebujesz jej wcale, ale jeśli chcesz zrobić bardziej wyrafinowane filtrowanie/transformację, to jest w porządku.

Jeśli więc nie chcesz zmieniać interfejsu API i nadal zwracasz wartość LinkedList, nie ma potrzeby zmiany implementacji. Ale jeśli chcesz skorzystać z funkcji Stream API, lepiej zmienić typ zwracania na Stream.

8

W przypadku braku zaksięgowanej odpowiedzi cytuję Brian Goetz, która odzwierciedla moje zdanie i podejrzewam, że wielu innych ".

W strumieniach i pętlach nie ma nic magicznego. Powinieneś napisać kod, który jest najbardziej czytelny, czytelny i możliwy do utrzymania. Każda z nich jest dopuszczalna.

0

Uważam, że jest to w dużej mierze uzależnione od przewidywanej wielkości kolekcji i praktycznego zastosowania programu. Ten pierwszy jest nieco bardziej wydajny, ale uważam go za mniej czytelny i nadal istnieją systemy działające na platformie Java 7 (np. Google App Engine). Ponadto łatwiej byłoby dodać bardziej złożone filtry do dalszych działań. Jeśli jednak najważniejszą kwestią jest wydajność, pójdę z tym pierwszym.

Powiązane problemy