2016-03-07 23 views
5

Próbuję opanować składnię strumienia w języku Java 8 za pomocą prostego przykładu. Przyjrzałam się innym podobnym pytaniom na ten temat, ale nie mogłem znaleźć rozwiązań, które pasowałyby do mojego przykładu i działałyby dla mnie. Zasadniczo próbuję byłaby następujący fragment z dwóch zagnieżdżonych pętli do korzystania z nowego strumienia API:Pętle zagnieżdżone Java 8 do strumienia

List<Car> filteredCars = new ArrayList<>(); 
    for (Car car : cars) { 

     for (Wheel wheel : wheels) { 

      if (car.getColor() == wheel.getColor() && 
        wheel.isWorking() == true) { 

       filteredCars.add(car); 
       break; 
      } 
     } 
    } 

    return filteredCars; 

Zarządzane wymyślić ten, który zwraca void:

return cars.stream().forEach(
      car -> wheels.stream() 
      .filter(wheel -> wheel.getColor() == car.getColor() && 
        wheel.isWorking() == true) 
      .collect(Collectors.toList())); 

Co jest nie tak ze strumieniem powyższa składnia i czego mi brakuje?

+6

jako ogólny porady, zatrzymaj zachowanie pierwszego spojrzenia na 'forEach'. Gdy już to zrozumiesz i zawsze będziesz najpierw patrzył na inne operacje strumieniowe, prawdopodobnie nigdy nie będziesz już musiał zadawać takiego pytania. Poza tym nie używaj warunków takich jak 'wheel.isWorking() == true', są one bezcelowe. Wystarczy użyć 'wheel.isWorking()', mówi samo za siebie. – Holger

Odpowiedz

9

Nie można wykonać dwóch operacji terminalowych - forEach i collect na tym samym Stream.

zamiast tego trzeba filtrować listę samochodów sprawdzanie każdego samochodu, jeśli ma pasujący kołem obrotowym:

List<Car> filteredCars = 
    cars.stream() 
     .filter (
      car -> wheels.stream() 
         .anyMatch(wheel -> wheel.getColor() == car.getColor() &&  
              wheel.isWorking())) 
     .collect(Collectors.toList()); 
2

Problem polega na tym, jesteś tworząc List (y) wewnątrz forEach i forEach zwraca void. Byłaby to równoważna z następujących pętli:

for (Car car : cars) { 
    List<Car> filteredCars = new ArrayList<>(); 
    for (Wheel wheel : wheels) { 

     if (car.getColor() == wheel.getColor() && 
       wheel.isWorking() == true) { 

      filteredCars.add(car); 
      break; 
     } 
    } 
} 

return filteredCars; // whoops cannot be accessed (scope) !!! 

można użyć filter w strumieniu cars i zbierania zastosowanie collect na przefiltrowanego strumienia, aby osiągnąć pożądane wyniki:

Predicate<Car> carCheck = car -> wheels.stream().anyMatch(wheel -> car.getColor() == wheel.getColor() && wheel.isWorking()); 

List<Car> filteredCars = cars.stream().filter(carCheck).collect(Collectors.toList()); 
Powiązane problemy