Java 8 convert List to Lookup Map

前端 未结 9 2055
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-12 03:29

I have a list of Station, in each Station there is a list of radios. I need to create a lookup Map of radio to Station. I know how to use Java 8 stream forEach to do it:

9条回答
  •  孤城傲影
    2021-01-12 04:16

    You can do it without Streams, of course, probably making it a bit more readable.

    Map LOOK_UP = new HashMap<>();
    List stations = ...
    
    
    stations.forEach(station -> {
        station.getRadios().forEach(radio -> {
             LOOK_UP.put(radio, station);
        });
    });
    

    This is not very different than a plain loop with:

    for (Station station : stations) {
         for (Radio radio : station.getRadios()) {
              LOOK_UP.put(radio, station);
         }
    }
    

    The obvious problem here is that LOOK_UP::put will always replace the value for a certain key, hiding the fact that you ever had duplicates. For example:

    [StationA = {RadioA, RadioB}]
    [StationB = {RadioB}]
    

    When you search for RadioB - what should you get as a result?

    If you could have such a scenario, the obvious thing is to change the LOOK-UP definition and use Map::merge:

        Map> LOOK_UP = new HashMap<>();
        List stations = new ArrayList<>();
    
        stations.forEach(station -> {
            station.getRadios().forEach(radio -> {
                LOOK_UP.merge(radio,
                              Collections.singletonList(station),
                              (left, right) -> {
                                  List merged = new ArrayList<>(left);
                                  merged.addAll(right);
                                  return merged;
                              });
            });
        });
    

    Another possibility is to throw an Exception when there are these kid of mappings:

    stations.forEach(station -> {
           station.getRadios().forEach(radio -> {
                LOOK_UP.merge(radio, station, (left, right) -> {
                     throw new RuntimeException("Duplicate Radio");
                });
           });
     });
    

    The problem with this last snippet, is that you can't really log the radio that is to be blamed for non-uniqueness. left and right are Stationss. If you want that too, you will need to use a merger that does not rely on Map::merge internally, like in this answer.

    So you can see, that it all depends on how and what exactly you need to handle.

提交回复
热议问题