2015-11-26 2 views
2

У меня есть мой собственный класс называется CheckIn с атрибутами day как String, workingHours как int и inProgress как boolean:Java 8 - как работать с лямбда с groupingBy и summingInt и использовать побитовый оператор

public class CheckIn { 
    public int id; 
    public String day; 
    public int workingHours; 
    public boolean inProgress; 

    public CheckIn(String day, in hours, boolean inProgress) { 
     this.day = day; 
     this.workingHours = hours; 
     this.inProgress = inProgress; 
    } 
} 

И у меня есть список записей в моей системе, и мне нужно собрать эти записи и сгруппировать их с днями и суммировать рабочие часы. Здесь хорошо, и я могу это сделать с лямбдой, но что, если тогда я хочу установить, то есть прогресс в true, если есть какие-то записи в истине?

// Suppose this is the inputs 
List<CheckIn> checkinsList = new ArrayList<>(); 
checkinsList.add(new CheckIn("26-11-2015",6,true)); 
checkinsList.add(new CheckIn("27-11-2015",6,false)); 
checkinsList.add(new CheckIn("26-11-2015",6,false)); 
checkinsList.add(new CheckIn("27-11-2015",4,false)); 
checkinsList.add(new CheckIn("26-11-2015",1,false)); 
checkinsList.add(new CheckIn("28-11-2015",6,false)); 
checkinsList.add(new CheckIn("28-11-2015",6,false)); 
checkinsList.add(new CheckIn("28-11-2015",6,true)); 


List<CheckIn> summary = new ArrayList<>(); 

checkinsList.stream().collect(Collectors.groupingBy(Function.identity(), 
    () -> new TreeMap<>(
     Comparator.<CheckIn, String>comparing(entry -> entry.day)), 
     Collectors.summingInt(entry -> entry.duration))).forEach((e, sumTargetDuration) -> { 
     CheckIn entry = new CheckIn(); 
     entry.day = e.day; 
     entry.duration = sumTargetDuration; 
     // Here my something like what I need? 
     entry.inProgress = e.inProgress; 
     summary.add(entry); 
}); 

Мне нужна summary Список содержит (в данном случае для входа) имеют 3 пунктов для этих 3-х дней с:

Результат, который я хочу, как это:

  • Первый пункт "26-11-2015" , 13 , true < - true, потому что есть 1 пункт за день «26-11-2015».
  • Второго элемент "27-11-2015" , 10 , false
  • Третий элемент "28-11-2015" , 18 , true

Я хочу, чтобы резюме приходит с inProgress верно, если есть какие-либо записи в этот день имеет inProgress == true это применимо с лямбдой?

ответ

2

Для выполнения этой задачи вам необходимо создать пользовательский сборщик. Проблема в том, что нет встроенного коллектора, который объединит несколько коллекторов и применит операцию отделки. В этом случае нам нужно будет объединить 3 коллектора: summingInt, reducing, которые будут or с каждым inProgress и mapping, которые будут отображаться на весь день.

Следующий класс будет содержать сводку во время процесса сбора и соответствующим образом рассчитывает результат. Мы могли бы добавить дополнительные проверки в отношении дня, потому что они должны быть одинаковыми в течение всего процесса, но я оставил их для простоты.

public class CheckInSummary { 

    private int workingHours; 
    private boolean inProgress; 
    private String day; 

    public void accept(CheckIn checkIn) { 
     workingHours += checkIn.workingHours; 
     inProgress = inProgress || checkIn.inProgress; 
     day = checkIn.day; 
    } 

    public CheckInSummary combine(CheckInSummary summary) { 
     workingHours += summary.workingHours; 
     inProgress = inProgress || summary.inProgress; 
     return this; 
    } 

    public CheckIn finish() { 
     return new CheckIn(day, workingHours, inProgress); 
    } 

} 

Затем вы можете создать коллектор из этого класса с помощью:

private static Collector<CheckIn, ?, CheckIn> summary() { 
    return Collector.of(
       CheckInSummary::new, 
       CheckInSummary::accept, 
       CheckInSummary::combine, 
       CheckInSummary::finish 
      ); 
} 

и наконец, вы можете использовать его как это:

List<CheckIn> result = 
     new ArrayList<>(checkinsList.stream() 
            .collect(groupingBy(c -> c.day, summary())) 
            .values()); 

Выход из тестового случая:

[[27-11-2015, 10, false], [26-11-2015, 13, true], [28-11-2015, 18, true]] 

Этот список не является отсортировано, но если вы хотите отсортировать его, вам просто нужен дополнительный звонок для sort(), сравнивающий день.

+0

Большое спасибо, я попробую это, когда снова открою свою IDE и подберу ответ, если будет работать. –

+0

Привет, я вернулся из своего отпуска и попробовал решение, и отлично поработал вам огромное спасибо. с небольшой модификацией, которую я использовал 'Collectors.groupingBy' и удалил' static' из метода collector. –

Смежные вопросы