2016-08-25 2 views
-2

java 8 Streams API를 사용하여 다른 목록에있는 동등한 항목의 특정 속성에 대한 모든 값을 어떻게 합계 할 수 있습니까? 예를 들어Java 8 스트림을 사용하여 다른 목록에있는 동일한 객체의 특정 속성을 어떻게 합계 할 수 있습니까?

, I는 다음과 같은 코드가 다음 List<PurchaseCancellation> cancellations 각 취소 PurchaseItemCancellation의리스트를 가지고있는 취소 목록을 보유

public class Streams { 

    static class PurchaseItemCancellation { 
     private Integer id; 
     private BigDecimal quantity; 

     // constructor 
     // getters and setters 
    } 

    static class PurchaseCancellation { 
     private Integer id; 
     private List<PurchaseItemCancellation> purchaseItemsCancellations; 

     // constructor 
     // getters and setters  
    } 

    public static void main (String ... args) { 

    PurchaseItemCancellation item1 = new PurchaseItemCancellation(1, new BigDecimal("10.00")); 
    PurchaseItemCancellation item2 = new PurchaseItemCancellation(2, new BigDecimal("20.00")); 
    PurchaseItemCancellation item3 = new PurchaseItemCancellation(3, new BigDecimal("30.00")); 
    PurchaseItemCancellation item4 = new PurchaseItemCancellation(4, new BigDecimal("40.00")); 

    PurchaseCancellation purchaseCancellation1 = new PurchaseCancellation(1, Arrays.asList(item1, item2)); 
    PurchaseCancellation purchaseCancellation2 = new PurchaseCancellation(2, Arrays.asList(item3, item4)); 
    PurchaseCancellation purchaseCancellation3 = new PurchaseCancellation(3, Arrays.asList(item4, item1)); 

    List<PurchaseCancellation> cancellations = Arrays.asList(purchaseCancellation1, purchaseCancellation2, purchaseCancellation3); 

    final Comparator<PurchaseItemCancellation> byID = (p1, p2) -> Integer.compare(p1.getId(), p2.getId()); 

    // List<PurchaseItemCancellation> itemsCancellations = cancellations.stream() .... 

    } 
} 

단계;

그래서 각 취소에 포함 된 PurchaseItemCancellation의 각 목록에 대해 동일한 항목의 속성 "수량"의 ​​합계가 필요합니다.

항목 1 : ID : 1 수량 : 20.00

항목 2 : ID : 2, 수량

결과는 List<PurchaseItemCancellation> 있어야 20.00

항목 3 : ID : 3, 수량 : 30.00

item4 : ID : 4, 수량 : 80.00

실행 코드에서 볼 수 있습니다 :

http://www.tutorialspoint.com/compile_java8_online.php?PID=0Bw_CjBb95KQMREE4TEJxa080NFE

피씨 :이 사이트에는 두 가지 성가신 버그가 있습니다.

첫 번째 버그 : 링크를 클릭하면 "HelloWorld.java"파일이 열립니다. 이 파일을 닫고 왼쪽 사이드 바에 "Streams.java"라는 올바른 파일을 엽니 다. 실행 버튼은 편집기의 맨 위에 있습니다.

두 번째 버그 : 파일이 수정 된 경우 편집기 맨 위에있는 "코드 공유"버튼을 클릭하여 새 공유 링크를 생성해야합니다. 죄송합니다. 나는 더 나은 온라인 Java 8 코드 편집기를 모른다.

도움이 될 것입니다.

+0

무엇이 당신의 질문입니까? – talex

+0

어쩌면 충분히 명확하지 않았을 수 있습니다. 미안합니다. 내 질문을 편집했습니다. –

답변

4

다음 코드에서 설명하는 프로세스는 다음과 같습니다. cancellations의 스트림을 가져 와서 PurchaseItemCancellation의 스트림으로 변환합니다. 그런 다음 우리는 단지 그것의 기본적인 요약을 수행합니다. 이 한 줄의 코드입니다

List<PurchaseItemCancellation> = cancellations.stream() 
    .filter(c -> c != null) 
    .map(PurchaseCancellation::getPurchaseItemCancellations) 
    .filter(l -> l != null) 
    .flatMap(List::stream) 
    .collect(Collectors.groupingBy(PurchaseItemCancellation::getId, 
     Collectors.reducing(BigDecimal.ZERO, PurchaseItemCancellation::getQuantity, BigDecimal::add))) 
    .entrySet().stream() 
    .map(e -> new PurchaseItemCancellation(e.getKey(), e.getValue())) 
    .collect(Collectors.toList()); 

(편집 난 그냥. 즉, 약간 다른 접근 방식을 필요로한다. 날 완전히 탈출 이유, 당신이 BigDecimal 값을 사용하는 것으로 나타났습니다)하지만, 일곱 개 위의 라인으로 나누어 무슨 일이 일어나는지 명확하게 알 수 있습니다. Stream<PurchaseCancellation>

    1. 변환은 홀수 null 취소를 필터링 -이 문제가되는 경우 모르겠어요.
    2. 로 변환 Stream<List<PurchaseItemCancellation>>
    3. null 목록이있는 모든 취소를 필터링합니다. 다시 걱정하지 않아도됩니다. Stream<PurchaseItemCancellation>-
    4. 변환 - 더 이상 그룹화는 취소로 그들은
    5. 사용 id하여 각 그룹이 양을 요약 내에서 그룹 멋진 계산기에서왔다. 지금 당신은
    6. 이 최종 결과의 목록을 가져옵니다 다른 Stream<PurchaseItemCancellation>
    7. 로 변환 항목의 또 다른 스트림으로 수량에
    8. 변환이지도를 ID에서 Map<Integer, BigDecimal> 있습니다.

    때로는 스트림을 사용하지 않는 것이 더 쉽습니다.

  • +0

    답변 해 주셔서 감사합니다. 결과는 반복 항목이없는 PurchaseItemCancellation의 고유 한 목록이어야합니다. 그러나 item.quantity에 대한 각 값이 합산됩니다. 따라서 다른 목록에있는 다른 항목에서 수량이 추가 된 고유 항목 1이 있습니다. –

    +0

    당신의 대답으로 나는 그 해결책에 가깝다. 모든 PurchaseItemCancellation을 단일 목록에 축적했지만 itens가 반복되었습니다. item.quantity를 추가하여 동일한 항목 (ID로 그룹화)을 병합하려면 어떻게해야합니까? –

    +1

    위의 내용이 가장 효율적인 방법은 아닙니다. 특히 중간 단계의 '지도'를 거치지 않고서는 가능한 것이어야한다고 생각하지만 어떻게해야할지 모르겠다. 또한, 'double'값으로 반올림하는 것의 위험성은 매우 미세하지 않습니다. 추가 된 소수점에도 불구하고 예제가 모두 효과적으로 정수입니다. 진정으로 정수인 경우'int' /'long'을 사용하십시오. 그렇지 않으면'double'이 좋을 것입니다. – dcsohl

    관련 문제