代码之家  ›  专栏  ›  技术社区  ›  hotmeatballsoup

在访问空组流时,使基于Java 8 groupingBy的映射“空安全”

  •  0
  • hotmeatballsoup  · 技术社区  · 5 年前

    这里是Java8。我有以下POJO:

    public enum VehicleType {
      Car,
      Motorcycle,
      Scooter,
      Skateboard
    }
    
    @Getter
    @Setter
    public class Driver {
      private String uuid;
      private Long numYearsDriving;
      private VehicleType vehicleType;
    }
    

    现在我有了下面的代码 List<Driver> 并将它们组织到一个 Map<VehicleType,List<Driver> 其中,钥匙是我们拥有的不同类型的车辆,每个值都是所有车辆的“子列表”(原始列表) Drivers 对于这些车型:

    List<Driver> allDrivers = getSomehow();
    
    Map<VehicleType,List<Driver>> driversByVehicleType = allDrivers.stream()
        .collect(Collectors.groupingBy(Driver::getVehicleType));
    

    到目前为止,一切顺利,我 认为 .现在我想检查一下那张地图,把所有的滑板车或滑板司机都叫来。我最好的尝试是:

    List<Driver> scooterSkateboarders = Stream
          .concat(
              driversByVehicleType.get(VehicleType.Scooter).stream(),
              driversByVehicleType.get(VehicleType.Skateboard).stream())
          .collect(Collectors.toList());
    

    ...然而,在编译时,它抛出了一个 NullPointerException 如果 allDrivers 没有 首先,包含所有滑板车/滑板驾驶员。所以我问:如果 所有司机 只包含,比如, Car 司机?

    0 回复  |  直到 5 年前
        1
  •  6
  •   Naman    5 年前

    如果你 不要 需要中间人吗 Map ,您可以过滤原始流:

    List<Driver> scooterSkateboarders = allDrivers.stream()
        .filter(driver -> EnumSet.of(Scooter, Skateboard).contains(driver.getVehicleType()))
        .collect(Collectors.toList());
    

    如果你 需要中间人吗 地图 :

    List<Driver> scooterSkateboarders = Stream
        .concat(
            driversByVehicleType.getOrDefault(VehicleType.Scooter, Collections.emptyList()).stream(),
            driversByVehicleType.getOrDefault(VehicleType.Skateboard, Collections.emptyList()).stream())
        .collect(Collectors.toList());
    

    或者,立即流式处理 entrySet

    List<Driver> scooterSkateboarders = driversByVehicleType.entrySet().stream()
        .filter(e -> EnumSet.of(Scooter, Skateboard).contains(e.getKey()))
        .map(Entry::getValue)
        .flatMap(List::stream)
        .collect(Collectors.toList());
    

    最后一个将是我首选的解决方案。

        2
  •  1
  •   Naman    5 年前

    使用Java-9及更高版本,您可以在使用groupBy时隐式使用过滤逻辑 Collectors.filtering 例如:

    Set<VehicleType> validVehicles = Set.of(VehicleType.Scooter, VehicleType.Skateboard);
    Map<VehicleType, List<Driver>> driversByVehicleType = allDrivers.stream()
            .collect(Collectors.groupingBy(Driver::getVehicleType,
                    Collectors.filtering(d -> validVehicles.contains(d.getVehicleType()),
                            Collectors.toList())));
    

    这将确保在按类型分组时,值中的空列表不符合筛选器的条件。