I have a String - Array
map thatlooks like this
dishIdQuantityMap[43]=[Ljava.lang.String;@301d55ce dishIdQuantityMap[42]=[Ljava.lang.String;@72cb31c2 dishIdQuantityMap[41]=[Ljava.lang.String;@1670799 dishIdQuantityMap[40]=[Ljava.lang.String;@a5b3d21
What I need to do is
- Create a new map, where key - only numbers extracted from String like this
( key -> key.replaceAll("\\D ","");
- Value - first value from array like this
value -> value[0];
- Filter an array so that only this paris left where
value > 0
I've spent an hour trying to solve it myself, but fail with .collect(Collectors.toMap());
method.
Could you please help me out.
UPD: The code I've done so far is just a shame, as I fail even to filter the map.
HashMap<Long, Integer> myHashMap = request.getParameterMap().entrySet().stream()
.filter(e -> Integer.parseInt(e.getValue()[0]) > 0)
.collect(Collectors.toMap(MapEntry::getKey, MapEntry::getValue));
CodePudding user response:
You can do it by using stream and an auxiliary KeyValuePair class. The KeyValuePair would be as simple as:
public class KeyValuePair {
public KeyValuePair(String key, int value) {
this.key = key;
this.value = value;
}
private String key;
private int value;
//getters and setters
}
Having this class you can use streams as bellow:
Map<String, Integer> resultMap = map.entrySet().stream()
.map(entry -> new KeyValuePair(entry.getKey().replaceAll("Key", "k"), entry.getValue()[0]))
.filter(kvp -> kvp.value > 0)
.collect(Collectors.toMap(KeyValuePair::getKey, KeyValuePair::getValue));
In the example I'm not replacing and filtering exactly by the conditions you need but, as you said you are having problems with the collector, you probably just have to adapt the code you currently have.
CodePudding user response:
I addressed this problem in the following order:
- filter out entries with
value[0] > 0
. This step is the last on your list, but with regards to performance, it's to put this operation at the beginning of the pipeline. It might decrease the number of objects that have to be created during the execution of themap()
operation; - update the entries. I.e. replace every entry with a new one. Note, this step doesn't require creating a custom class to represent a key-value pair, AbstractMap.SimpleEntry has been with as for a while. And now instead of instantiating
AbstractMap.SimpleEntry
we can simply use a static methodentry()
of theMap
interface; - collect entries into the map.
public static Map<Long, Integer> processMap(Map<String, String[]> source) {
return source.entrySet().stream()
.filter(entry -> Integer.parseInt(entry.getValue()[0]) > 0)
.map(entry -> updateEntry(entry))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue));
}
private static Map.Entry<Long, Integer> updateEntry(Map.Entry<String, String[]> entry) {
return Map.entry(parseKey(entry.getKey()), parseValue(entry.getValue()));
}
The logic for parsing keys and values was extracted into separate methods to make the code cleaner.
private static Long parseKey(String key) {
return Long.parseLong(key.replaceAll("\\D ",""));
}
private static Integer parseValue(String[] value) {
return Integer.parseInt(value[0]);
}
public static void main(String[] args) {
System.out.println(processMap(Map.of("48i;", new String[]{"1", "2", "3"},
"129!;", new String[]{"9", "5", "9"})));
}
Output
{48=1, 129=9}