2017-02-23 11 views
4

리포지토리의 데이터를 반환하는 N 목록이 있습니다. 이 세 목록 중 첫 번째가 아닌 공백을 반환하고 싶습니다 (각각 다른 SQL을 실행하여 데이터를 가져옵니다).Java 8에서 첫 번째 비어 있지 않은 목록을 늦게 반환

캐치는 느리게 수행하기 때문에 수용 가능한 결과를 이미 찾은 경우 데이터베이스에서 SQL을 실행할 필요가 없습니다. 내 코드가 (수정 된)

@Override 
public List<Something> dataService(Data data) { 

return firstNonEmptyList(repository.getDataWayOne(data.getParameter()), 
         repository.getDataWayTwo(data.getParameter()), 
         repository.getDataWayThree(data.getParameter().getAcessoryParameter()) 
         Collections.singletonList(repository.getDefaultData(data.getParameter())); 

} 

@SafeVarargs 
private final List<Something> firstNonEmptyList(List<Something>... lists) { 
for (List<Something> list : lists) { 
    if (!list.isEmpty()) { 
    return list; 
    } 
} 

return null; 

} 

이 작동하지만 게으른 없습니다. 어떤 아이디어?

+0

내가 틀렸다면 정정 해주세요. 그러나 lambdas 내부에서 목록 호출을 감추면 게으른다고 생각합니다. 'firstNonEmptyList'에서 당신이 원하는 것을 찾을 때까지 (즉, 비어 있지 않은리스트를 반환하는) 각각의 람다를 평가할 것입니다. 람다라고 불리는 것이 결코 쿼리를 실행하지 않습니다. 어쨌든, shmosel이 제공 한 솔루션은 제가 설명하고 더 우아합니다. – Gabriel

답변

9

당신은 공급 업체의 스트림을하고 그 결과 찾을 때까지 만남의 순서로 평가할 수 :

return Stream.<Supplier<List<Something>>>of(
      () -> repository.getDataWayOne(data.getParameter()), 
      () -> repository.getDataWayTwo(data.getParameter()), 
      () -> repository.getDataWayThree(data.getParameter().getAcessoryParameter()), 
      () -> Collections.singletonList(repository.getDefaultData(data.getParameter())) 
     ) 
     .map(Supplier::get) 
     .filter(l -> !l.isEmpty()) 
     .findFirst() 
     .orElse(null); 

각 공급 업체가 실제로 실행 map() 때까지 시도하지 않고, 결과 세트에 액세스하는 방법을 정의합니다. filter()map()stateless 작업이므로 각 공급자가 호출되고 그 결과는 다음에 시도되기 전에 유효성이 검사됩니다. 비어 있지 않은 결과가 발견되면 findFirst()short-circuiting이기 때문에 스트림이 즉시 종료됩니다.

+1

이것은 사람들이 어지럽게 만드는 Java 8 답변 중 하나입니다. 단계별로 설명 할 수만 있다면 왜 게으른로드입니까? –

+0

이것은 훌륭한 대답입니다. 가장 Java8-ic 방식으로, 제 프랑스어를 용서합니다! – khachik

+0

@ GrzegorzGórkiewicz 나는 노력했다. 바라건대 이제는 조금 더 명확 해지기를 바랍니다. – shmosel

3

스트림이 차 한잔이 아니더라도 람다를 사용하여 원래 코드를 약간만 수정하면 원하는 것을 얻을 수 있습니다.

+0

우연의 일치, 내 마지막 코멘트는 정확히 여기서 한 짓입니다. 그것은 작동합니다 (나는 추측합니다), 그러나 문제는 그것이 게으름에 대한 의도를 숨기는 것입니다. 이 경우 더 많은 기능적 스타일을 환영합니다. – Gabriel

+0

필자는 실제로 그 반대가 사실이라고 생각합니다. 'firstNonEmptyList'의 단락 동작은 매우 명백합니다. 스트림을 사용하면 모든 사람이 아닌 스트림 API를 잘 알고 있다면 분명합니다. 이 메서드에 대한 Javadocs를 사용하면 훨씬 더 명확 해집니다. –

+0

이것은 또한 지연로드를 포함하여 모든 테스트를 통과하고 통과했습니다. 알겠습니다. 나는 보조 방법을 없애기 때문에 shmosel의 것을 사용할 것이다. –