Zamiana pętli na streamy

0

Witam,

Mam taki kawałek kodu i nie wiem jak zastąpić pętle streamami. Skoro mam dwie pętle, powinienem zastąpić je dwoma streamami?

public List<String> getTextByIndex(List<WebElement> elements, List<Integer> indexes){
        List<String> text = new ArrayList<String>();

        for (WebElement element: elements) {
            for (Integer index: indexes) {
                if (elements.indexOf(element) == index){
                    text.add(element.getText());
                }
            }
        }
        return text;
}
2

Ale co Ty właściwie próbujesz zrobić? Chcesz zostawić takie elementy w wynikowej liście, które mają indexy podane w drugiej liście?

Bo jeśli tak, to wystarczy:

return IntStream
            .range(0, elements.size() - 1)
            .filter(indexes::contains)
            .mapToObj(text::get)
            .collect(Collectors.toList());

PS: Ewentualnie, jak kombinujesz coś z takim czymś to możesz jeszcze googlać "list intersection" albo "list difference".

1
indexes.stream()                      // 1.
  .filter(i -> i < elements.size())   // 2.
  .map(elements::get)                 // 3.
  .map(WebElement::getText)           // 4.
  .collect(Collectors.toList());      // 5.

1. Utworzenie streama na podstawie kolekcji indexes
2. Przefiltrowanie elementów streama, by były tam tylko elementy mniejsze niż rozmiar kolekcji elements (ograniczenie indeksów do istniejących w kolekcji elements). Zrobione jest tu założenie, że kolekcja indexes zawiera tylko liczby naturalne - jeśli z jakichś względów potrzebujesz, możesz odfiltrować elementy null (np. filter(Objects::nonNull)) oraz mniejsze od 0.
3. Zmapowanie indeksów na elementy z kolekcji elements - wykorzystanie metody List.get(Integer index).
4. Zmapowanie elementów WebElement na wartość zwracaną przez funkcję WebElement.getText().
5. Zebranie wszystkich przetworzonych elementów przez stream do kolekcji - tutaj pobrane do List przy użyciu standardowego collectora z klasy java.util.stream.Collectors.

0

Dzięki! Właśnie o to mi chodziło :)

1

@catom:
@Salci:

Rozwiązanie @catom ma dwa nie obsłużone corner-case'y:

  • jeśli w indexes są duplikaty, w wynikowej kolekcji też będą
  • jeśli w indexes jest ujemna liczba, poleci IndexOutOfBoundsException
0
catom napisał(a):

Odnośnie List<Integer> i liczb ujemnych - mam metodę getElementsTextByIndexes() i parametr List<Integer> indexes - sugeruje to raczej, jakie powinno być użycie tej metody i jakie parametry powinniśmy tam wprowadzić - możemy zastosować dokładnie tę samą metodę, o której mówiłeś w przypadku nulli - Gdyby znalazła się tam liczba ujemna, to szukałbym problemu gdzie indziej.

catom napisał(a):

Jasne, najbezpieczniej byłoby dostarczyć API niepozwalające na podanie nieprawidłowych parametrów, tylko nasza rozmowa przestaje mieć jakikolwiek związek z przedstawionym problemem. Jakaś implementacja UnsignedInt, jakiś builder dla listy indexes, który nie pozwoliłby na np. dodanie indeksu spoza indeksów listy elements itd. Dla mnie, zarówno podanie null, jak i podanie -1, jest nieprawidłowym użyciem API i w obydwu przypadkach skończy się wyjątkiem.

@catom: Nie chcę filozofować, ale moim zdaniem -1 to taki sam int jak 1, natomiast null to coś zupełnie innego. Jest ogromna masa operacji liczbowych które mają sens i dla dodatnich i dla ujemnych liczb (np. max,min,intersect,sum, etc. ). To że akurat operacja o której mówimy List.get(index) takiej nie obsługuje, to trudno, trzeba się przed tym zabezpieczyć - dlatego o tym mówię w punkcie 2. mojej odpowiedzi. Z nullem jest trochę inaczej, bo żadna operacja liczbowa dla niego nie przejdzie (chyba że jest napisania dookoła API z nullami jak 20 lat temu i sobie zmienić tego nulla na jakiegoś defaulta). Więc ten argument z szukaniem problemu gdzie indziej, moim zdaniem, ma sens tylko dla nulli - bo jak mówiłem -1 to taki sam int jak 1 i ogrom operacji na intach ma sens również dla ujemnych.

1 użytkowników online, w tym zalogowanych: 0, gości: 1