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

hot*_*oup 3 java java-8 java-stream

Java 8 在这里。我有以下 POJO:

public enum VehicleType {
  Car,
  Motorcycle,
  Scooter,
  Skateboard
}

@Getter
@Setter
public class Driver {
  private String uuid;
  private Long numYearsDriving;
  private VehicleType vehicleType;
}
Run Code Online (Sandbox Code Playgroud)

现在我有以下代码,它接受 aList<Driver>并将它们组织到 a 上Map<VehicleType,List<Driver>,其中键是我们拥有的不同类型的车辆,每个值都是Drivers这些车辆类型的所有“子列表”(原始列表的):

List<Driver> allDrivers = getSomehow();

Map<VehicleType,List<Driver>> driversByVehicleType = allDrivers.stream()
    .collect(Collectors.groupingBy(Driver::getVehicleType));
Run Code Online (Sandbox Code Playgroud)

到目前为止,很好,我认为。现在我想检查该地图并获取踏板车或滑板的所有驱动程序。我最好的尝试:

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

...编译,但是,它会抛出一个NullPointerExceptionif 开始时allDrivers 包含任何滑板车/滑板驱动程序。所以我问:如果allDrivers只包含Car驱动程序,如何使我的代码“空安全” ?

War*_*ard 6

如果您没有需要的中间Map,可以过滤原始数据流:

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

如果您确实需要中间件Map

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

或者,立即流式传输 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());
Run Code Online (Sandbox Code Playgroud)

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