2017-01-13 1 views
5

를 합산 :그룹 나는 세금의 목록이 BigDecimal를

TaxLine = title:"New York Tax", rate:0.20, price:20.00 
TaxLine = title:"New York Tax", rate:0.20, price:20.00 
TaxLine = title:"County Tax", rate:0.10, price:10.00 

TaxLine 클래스가 나는 독특한 titlerate에 그들에게 기반을 결합하고 싶은

public class TaxLine { 
    private BigDecimal price; 
    private BigDecimal rate; 
    private String title; 
} 

입니다, 다음을 추가 price, 예상 :

TaxLine = title:"New York Tax", rate:0.20, price:40.00 
TaxLine = title:"County Tax", rate:0.10, price:10.00 

어떻게 이것을 Java 8에서 수행 할 수 있습니까?

은 필드를 합산하지 않으며 두 필드로만 그룹화 할 수 있습니다.

답변

8

주요 링크 된 문제와 동일합니다, 당신은 단지 요약하는 다른 다운 스트림 콜렉터가 필요합니다

List<TaxLine> flattened = taxes.stream() 
    .collect(Collectors.groupingBy(
     TaxLine::getTitle, 
     Collectors.groupingBy(
      TaxLine::getRate, 
      Collectors.reducing(
       BigDecimal.ZERO, 
       TaxLine::getPrice, 
       BigDecimal::add)))) 
    .entrySet() 
    .stream() 
    .flatMap(e1 -> e1.getValue() 
     .entrySet() 
     .stream() 
     .map(e2 -> new TaxLine(e2.getValue(), e2.getKey(), e1.getKey()))) 
    .collect(Collectors.toList()); 
0

다음과 같이 Taxline 클래스 내에 TitleRate라는 새 클래스를 정의하여 그룹화 된 필드를 요약 할 수 없습니다.

class Taxline{ 
     public static class TitleRate { 
      public TitleRate(String title, int taxline) { 
       ... 
      } 

     } 

     public TitleRate getTitleRate() { 
      return new TitleRate(title, taxline); 
     } 
    } 

제목과 세금을 그룹화하여 가격을 합산하려면 다음을 사용할 수 있습니다.

Map<TitleRate, List<Taxline>> groupedData = people.collect(Collectors.groupingBy(Taxline::getTitleRate)); 

    List<Taxline> groupedTaxLines = new ArrayList<Taxline>(); 
    BigDecimal groupedRate = BigDecimal.ZERO; 
    for (Map<TitleRate, List<Taxline>> entry : groupedData.entrySet()) 
    { 
    for(Taxline taxline : entry.getValue()){ 
     groupedRate = groupedRate.add(taxline.getPrice()); 
    } 
    groupedTaxLines.add(new Taxline(entry.getKey().getTitle, entry.getKey().getRate(), groupedRate)); 
     groupedRate = BigDecimal.ZERO; 
    } 
0

한 가지 방법은 그룹화 할 필드 집합에 대한 개체를 만드는 것입니다. 그 클래스는 훌륭한 헬퍼 메소드를 제공하기 위해 만들어 질 수 있습니다.

그래서, 원래 클래스는 다음과 같이 완료와 함께 :

public final class TaxLine { 
    private String title; 
    private BigDecimal rate; 
    private BigDecimal price; 
    public TaxLine(String title, BigDecimal rate, BigDecimal price) { 
     this.title = title; 
     this.rate = rate; 
     this.price = price; 
    } 
    public String getTitle() { 
     return this.title; 
    } 
    public BigDecimal getRate() { 
     return this.rate; 
    } 
    public BigDecimal getPrice() { 
     return this.price; 
    } 
    @Override 
    public String toString() { 
     return "TaxLine = title:\"" + this.title + "\", rate:" + this.rate + ", price:" + this.price; 
    } 
} 

그리고 다음과 같이 정의 된 그룹화 도우미 클래스 :

public final class TaxGroup { 
    private String title; 
    private BigDecimal rate; 
    public static TaxLine asLine(Entry<TaxGroup, BigDecimal> e) { 
     return new TaxLine(e.getKey().getTitle(), e.getKey().getRate(), e.getValue()); 
    } 
    public TaxGroup(TaxLine taxLine) { 
     this.title = taxLine.getTitle(); 
     this.rate = taxLine.getRate(); 
    } 
    public String getTitle() { 
     return this.title; 
    } 
    public BigDecimal getRate() { 
     return this.rate; 
    } 
    @Override 
    public int hashCode() { 
     return this.title.hashCode() * 31 + this.rate.hashCode(); 
    } 
    @Override 
    public boolean equals(Object obj) { 
     if (obj == null || getClass() != obj.getClass()) 
      return false; 
     TaxGroup that = (TaxGroup) obj; 
     return (this.title.equals(that.title) && this.rate.equals(that.rate)); 
    } 
} 

결합 된 광고 항목에 대한 귀하의 코드는이, 이상 많은 분할 여러 부분을 볼 수있는 행 :

List<TaxLine> lines = Arrays.asList(
     new TaxLine("New York Tax", new BigDecimal("0.20"), new BigDecimal("20.00")), 
     new TaxLine("New York Tax", new BigDecimal("0.20"), new BigDecimal("20.00")), 
     new TaxLine("County Tax" , new BigDecimal("0.10"), new BigDecimal("10.00")) 
); 
List<TaxLine> combined = 
     lines 
     .stream() 
     .collect(Collectors.groupingBy(TaxGroup::new, 
             Collectors.reducing(BigDecimal.ZERO, 
                  TaxLine::getPrice, 
                  BigDecimal::add))) 
     .entrySet() 
     .stream() 
     .map(TaxGroup::asLine) 
     .collect(Collectors.toList()); 

그런 다음 입력/출력을 인쇄 할 수 있습니다.

System.out.println("Input:"); 
lines.stream().forEach(System.out::println); 
System.out.println("Combined:"); 
combined.stream().forEach(System.out::println); 

이 생산하려면

Input: 
TaxLine = title:"New York Tax", rate:0.20, price:20.00 
TaxLine = title:"New York Tax", rate:0.20, price:20.00 
TaxLine = title:"County Tax", rate:0.10, price:10.00 
Combined: 
TaxLine = title:"New York Tax", rate:0.20, price:40.00 
TaxLine = title:"County Tax", rate:0.10, price:10.00