2017-09-12 10 views
1

나는 굉장히 봤지만 대답을 찾지 못했습니다.두 개의 매개 변수로 스트림 필터

parentList.forEach(p -> { 
     childList 
       .stream() 
       .filter(c -> p.id() == c.parentId()) 
       .<...continue working on stream...> 
    }); 

나는 내가 술어 인수를 전달할 필요가 있다고 보인다 술어 "필터"부품을 교체하는 방법을 수있는 방법 찾을 수 없습니다 : 여기 내가 가진 무엇인가?

+0

현재'filter()'호출의 문제점은 무엇입니까? – Eran

+0

다른 곳에서이 필터를 재사용하려는 경우 - 복사/붙여 넣기를 피하십시오. 그것 이외에 - 아무것도. – lapkritinis

+1

단순한 술어에서는 복사/붙여 넣기를 피할 가치가 없습니다. 복잡한 조건을 가지고 있다면, 그 곳에서 호출 할 수있는 메소드를 만든 다음'c -> someMethodComparing (c, p)'를 사용하십시오. – lucasvw

답변

4

귀하의 문제가 c 비록 당신의 조건에 매개 변수입니다 때문에, 다른 술어마다 사용하고 있다는 것입니다, p도 다릅니다

final Node p; 
Predicate<Node> matchesParentId = c -> p.id() == c.id(); 

기존의 코드를 확인 컴파일 이유는 p는 점이다 forEach 블록의 범위에 실제로 최종이므로, 해당 범위 내의 Predicate에서 최종 필드로 사용할 수 있으며, 수명은 1 회 forEach 반복입니다.

당신은 할 수 :

parentList.forEach(p -> { 
    childList 
      .stream() 
      .filter(matchesId(p)) 
      .<...continue working on stream...> 
}); 

private Predicate<Node> matchesId(Node other) { 
    return node -> node.id() == other.id(); 
} 

하지만 당신은 p이 변화로 하나 Predicate를 생성하고 재사용 할 수 없습니다.


당신은 BiPredicatecurryPredicate로를 작성할 수 있습니다. 불행히도 Java는 카레 메서드를 제공하지 않으므로 직접 제공해야합니다.

private <T,U> Predicate<U> curry(BiPredicate<T,U> biPredicate, T t) { 
    return u -> biPredicate.test(t, u); 
} 

BiPredicate<Node,Node> nodesMatch = (a,b) -> a.id() == b.id(); 

parentList.forEach(p -> { 
    childList 
     .stream() 
     .filter(curry(nodesMatch, p)) 
     .<...continue working on stream...> 
}); 

이것은 이전 솔루션보다 훨씬 많은 것을 구매하지는 않지만 조금 더 FP-nerdy입니다. p에 대해 여전히 새로운 Predicate을 생성하고 있습니다. 물론 curry() 메소드를 사용하는 대신 인라인으로 처리 할 수 ​​있습니다.

.filter(c -> nodesMatch.test(p, c)) 

동적으로 연결하려면 BiPredicate<Node,Node>을 선택할 수 있습니다. BiPredicate을 초기화하는 데 비용이 많이 든다면, 많은 사람들이이를 대기로 싸서 싸게 될 것입니다.


또는 당신이 술어에 전체를 제출 할 수있는 하나의 객체로 pc을 매핑 할 수 있습니다 : 여기

Predicate<Pair<Node,Node>> nodesMatch = pair -> 
    pair.left().id() == pair.right().id(); 

parentList.forEach(p -> { 
    childList 
     .stream() 
     .map(c -> new Pair<Node>(c, p)) 
     .filter(nodesMatch) 
     .map(pair -> pair.left()) 
     .<...continue working on stream...> 
}); 

(Pair입니다 가상하지만, 제 3의 숫자 (예 : 구아바)가 하나를 제공하거나 자신의 롤을 사용하거나 new Node[] { c, p }를 사용하십시오.

+0

도움과 다른 방법을 제공 해주신 것에 대해 감사드립니다. – lapkritinis