import java.math.BigDecimal; import java.time.Duration; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collector; import java.util.stream.Collectors; class TripAnalyzerApp1 { private static final List TRIPS = List.of( new Trip(TripType.BUSINESS, "Tokyo", Duration.ofHours(5),LocalDateTime.of(2025, 5, 25, 8, 0), "Thomas Anderson", new BigDecimal("1200.00")), new Trip(TripType.BUSINESS, "New York", Duration.ofHours(8), LocalDateTime.of(2025, 5, 26, 9, 30), "John Wick", new BigDecimal("2500.00")), new Trip(TripType.VACATION, "Phuket", Duration.ofHours(3), LocalDateTime.of(2025, 6, 1, 10, 15), "Johnny Silverhand", new BigDecimal("850.00")), new Trip(TripType.VACATION, "Paris", Duration.ofHours(7), LocalDateTime.of(2025, 6, 5, 12, 0), "Ted Logan", new BigDecimal("1800.00")), new Trip(TripType.EDUCATION, "London", Duration.ofHours(6), LocalDateTime.of(2025, 5, 29, 7, 45), "Jack Traven", new BigDecimal("1350.00")), new Trip(TripType.EDUCATION, "Boston", Duration.ofHours(9), LocalDateTime.of(2025, 6, 10, 8, 30), "John Constantine", new BigDecimal("1950.00")), new Trip(TripType.MEDICAL, "Singapore", Duration.ofHours(4), LocalDateTime.of(2025, 5, 30, 14, 0), "Kevin Lomax", new BigDecimal("1100.00")), new Trip(TripType.RELOCATION, "Berlin", Duration.ofHours(10), LocalDateTime.of(2025, 6, 15, 11, 30), "Jonathan Harker", new BigDecimal("3200.00"))); public static void main(String[] args) { final var analyzer = new TripDurationAnalyzer(); final var result = analyzer.averageOfTypeDestinationDurations(TRIPS); System.out.println("Average trip duration: " + (result.isPresent() ? result.getAsDouble() + " minutes" : "No data")); } } class TripDurationAnalyzer { public OptionalDouble averageOfTypeDestinationDurations(List trips) { final var averageDurationsByType = trips.stream().collect(groupByTypeWithDestinationAverages()).values(); return averageDurationsByType.stream() .filter(OptionalDouble::isPresent) .mapToDouble(OptionalDouble::getAsDouble) .average(); } private static Collector> groupByTypeWithDestinationAverages() { return Collectors.groupingBy(Trip::type, averageMinDurationCollector()); } private static Collector averageMinDurationCollector() { return Collectors.collectingAndThen( groupDestinationsByMinDuration(), DurationStatistics::calculateAverageDuration); } private static final Comparator BY_DURATION = Comparator.comparing(Trip::duration); private static Collector> groupDestinationsByMinDuration() { return Collectors.groupingBy( Trip::destination, Collectors.collectingAndThen( Collectors.minBy(BY_DURATION), opt -> opt.map(Trip::duration).orElse(null))); } } final class DurationStatistics { public static OptionalDouble calculateAverageDuration(Map map) { final var nonNullDurations = map.values().stream().filter(Objects::nonNull); return nonNullDurations.mapToLong(Duration::toMinutes).average(); } } enum TripType { BUSINESS, VACATION, EDUCATION, MEDICAL, RELOCATION; } record Trip( TripType type, String destination, Duration duration, LocalDateTime departureTime, String travelerName, BigDecimal cost) {}