Collect as HashMap<String,String> from a List or Stream of objects without a POJO in java 8

Viewed 743

I have a list of objects out of which I have to create a HashMap<String,String> or ConcurrentHashMap<String,String> after applying certain logic on each of the objects in the list. Here is the code which works perfectly fine without using java 8.

 for (Model model : parser.getList()) {
       String name = model.getName();
       String val = parser.getValue(arr, name);
       map.putIfAbsent(name, val);
 }

I was able to translate it as

Map<String, String> map = new HashMap<>();
parser.getList().forEach(model -> map.putIfAbsent(model.getName(),parser.getValue(arr,model.getName())));

However I wanted to explore the usage of Collectors.toMap and see if I can leverage that for this use case. I was trying to do something like below but that isn't the correct usage as I am unable to call the method parser.getValue with params in toMap().

 Map<String,String> valMap = parser.getFieldList().stream().collect(Collectors.toMap(Model::getName,parser.getValue(arr,Model::getName),(left,right)->right),HashMap::new); 

I was able to use Collectors.toMap() when I created a POJO ValHolder to hold the values as below.

Map<String,String> tranMap = parser.getFieldList().stream().map(model -> {
        return new ValHolder(model.getName(),parser.Value(dataArray,model.getName()));
}).collect(Collectors.toMap(ValHolder::getName,ValHolder::getValue,(x,y)->y,HashMap::new));

The POJO created to hold the value is as below

class ValHolder {

    String name;
    String value;

    public String getName() {
        return name;
    }

    public String getValue() {
        return value;
    }

    ValHolder(String name, String val){
        fieldName = name;
        value = val;
    }
}

I would like to know if toMap() can be used without creating a POJO to hold the values to be accessible easily via Method references.

1 Answers

You don't have to use a method reference.

For example:

Map<String,String> valMap = 
    parser.getFieldList()
          .stream()
          .collect(Collectors.toMap(Model::getName,
                                    m -> parser.getValue(arr,m.getName()),
                                    (left,right)->right,
                                    HashMap::new));

Or, you can use a Map.Entry implementation instead of your POJO:

Map<String,String> tranMap = 
    parser.getFieldList()
          .stream()
          .map(model -> new SimpleEntry<>(model.getName(),parser.getValue(dataArray,model.getName())))
          .collect(Collectors.toMap(Map.Entry::getKey,
                                    Map.Entry::getValue,
                                    (x,y)->y,
                                    HashMap::new));
Related