I am trying to refactor not very elegant code using a stream. I have a HashMap containing strings and MyObjects, and currently iterates through a for loop like this:
Map<String, MyObject> map = new HashMap<>(); Map<String, MyObject> objectsToAdd = new HashMap<>(); for(MyObject object : map.values()){ String idToAdd = object.getConnectedToId(); if(StringUtils.isEmpty(idToAdd) { continue; } if(idToAdd.substring(0,1).equals("i")){
Since I only care about identifiers, I started by using a map operation to get only identifiers, and then a filter operation to eliminate empty ones.
The next part is what I came across. The first thing I tried was to use the Collectors groupingBy command so that I could group the elements based on the first id character, and I ended up with this:
map.values().stream() .map(myObject -> myObject.getConnectedToId())
This link helped shorten using stream collectors: Stream Reduction
We have at least two problems with this code: 1) collect is an operation that closes the stream, and we have not finished yet, and 2) we still need the original object, but now it has been reduced to a map of connected ToIds.
Q1) Is there an intermediate operation that allows us to group objects based on the first id character?
Q2) How can we do this without reducing the collection to ids only?
Q3) And, finally, as soon as the collection is grouped (there will be two), how can we perform separate functions in each group, as in the source code?
Final Solution (thanks @Holger and @Flown for help)
Map<Character, Function<String, MyObejct>> methodMapping = new HashMap<>(); methodMapping.put('i', service1::method1); methodMapping.put('d', service2::method2); Map<String, MyObject> toAdd = map.values().stream().map(MyObject::getConnectedToId) .filter(StringUtils::isNotEmpty) .map(id -> methodMapping.getOrDefault(id.charAt(0), i -> null).apply(id)) .filter(Objects::nonNull) .collect(Collectors.toMap(MyObject::getId, Function.identity(), (mo1, mo2) -> mo2)); map.putAll(toAdd);
To avoid the exception of parallel modification, you must first save the objects in the temporary map when performing flow operations, and then after they are completed add them to the final map.