2017-05-31 40 views
13

Jestem obecnie tworzenie Map<String, Map<LocalDate, Integer>> takiego, gdzie Integer reprezentuje sekundach:Jak uzyskać niestandardowy typ zamiast Integer podczas korzystania z Collectors.summingInt?

Map<String, Map<LocalDate, Integer>> map = stream.collect(Collectors.groupingBy(
      x -> x.getProject(), 
      Collectors.groupingBy(
       x -> x.getDate(), 
       Collectors.summingInt(t -> t.getDuration().toSecondOfDay()) 
      ) 
     )); 

Jak mogłem zamiast stworzyć Map<String, Map<LocalDate, Duration>>?

+0

Zauważam, że ['java.time.Duration'] (https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html) nie ma' toSecondOfDay() 'metoda. Czy używasz innego typu lub jest to błąd dla 'getSeconds()'? –

+0

@DidierL Używam LocalTime do zapisywania czasu trwania, Wygląda ładniej w DBMS. – Alex78191

+0

Nie sądzę, że dobrym pomysłem jest niewłaściwe użycie typu Java ze względu na reprezentację bazy danych. Zamiast tego należy użyć konkretnego konwertera, aby odwzorować wybrany typ bazy danych - jeśli domyślna konwersja nie działa. –

Odpowiedz

8

Aby zmienić Integer z Collectors.summingInt do Duration, wystarczy zastąpić że Collector z:

Collectors.collectingAndThen(
    Collectors.summingInt(t -> t.getDuration().toSecondOfDay()), 
    Duration::ofSeconds 
) 
1

Jeśli uzywasz rzeczywistą Duration dla getDuration() (zamiast LocalTime), można też podsumować bezpośrednio Duration „s następująco:

Map<String, Map<LocalDate, Duration>> map = stream.collect(Collectors.groupingBy(
     MyObject::getProject, 
     Collectors.groupingBy(
       MyObject::getDate, 
       Collectors.mapping(MyObject::getDuration, 
         Collectors.reducing(Duration.ZERO, Duration::plus)) 
     ) 
)); 

z korzyścią, że również sumuje nanosekund, a może być również uogólnione na inne typy.

Należy jednak pamiętać, że tworzy wiele pośrednich instancji Duration, które mogą mieć wpływ na wydajność.