Get an array from a map and convert the keys - java

I have a map<String, Object> and an array of int[] which is supposed to contain the map keys.
Is there a nice and short way to convert the keys to int, without using a loop?
myArray = myMap.keySet().toArray(new int[5]);
I useJava 8.
Thanks!

Assuming all your String keys can be safely parsed as integers :
int[] keys = myMap.keySet().stream().mapToInt(Integer::parseInt).toArray();
keySet() returns a Set<String>.
stream() returns a Stream<String>.
mapToInt() maps that Stream<String> to an IntStream by applying Integer.parseInt() on each String.
toArray() returns an array of all the elements of the IntStream.

myMap.keySet().toArray(); // returns an array of keys
myMap.values().toArray(); // returns an array of values
Attention!
Should be noted that the ordering of both arrays may not be the same.

Related

How to collect two string streams into a Map in Java? [duplicate]

This question already has answers here:
How to create a map out of two arrays using streams in Java?
(3 answers)
Closed 1 year ago.
I have two Arrays as below:
k[] = {"K1","K2","K3"}
v[] = {"V1","V2","V3"}
I want to iterate these two arrays using Stream API in such a way so that I collect them as a Map as
[K1=V1,K2=V2,K3=V3]
Assuming both arrays have the same length, you could create a stream with the indexes. This can be done with IntStream.range(start,end) where the start is 0 and the end the size of your array. Because we use range, the end will not be included.
In this stream, you need to collect the result to a map, the key will be the value in first array with the given index, the value will be the value in the second array with the given index.
Do note that an IntStream is not the same as a Stream<Integer>. In this case, we will need a stream of Integers so that we can collect them in the Collector (Collector does not work with primitive types). To do this, call the method .boxed() to convert it to a Stream<Integer>
String k[] = {"K1", "K2", "K3"};
String v[] = {"V1", "V2", "V3"};
Map<String, String> result = IntStream.range(0, k.length).boxed().collect(Collectors.toMap(i -> k[i], i -> v[i]));
This gives the following result
{K1=V1, K2=V2, K3=V3}
IntStream.range(0, k.length).collect(Collectors.toMap(i -> k[i], i -> v[i]));

JavaPairRDD convert key-value into key-list

I have a JavaPairRDD containing (Key, Value) which I want to group by Keys and make the "second column" a list with all values seen for that key. I am currently using the groupby() function, which does the key aggrupation correctly but converts my values to an Iterable of Long. This is,
Key1 Iterable<Long>
Key2 Iterable<Long>
...
Is there any way to force this function to use a List of Longs instead of an Iterable object?
Key1 List<Long>
Key2 List<Long>
...
I read something about a function called combineByKey() but I think this is not a use case. Probably I need to use reduceByKey but I am not seeing it. It should be something like this:
myRDD.reduceByKey((a,b) -> new ArrayList<Long>()) //and add b to a
In the end, I want to combine values to obtain a Key n, List<Long> RDD.
Thank you for your time.
You can try something like this:
JavaPairRDD <String, List<long>> keyValuePairs = rdd.map(t -> {
return new Tuple2(t._1, Arrays.asList(new long[]{t._2}));
}).reduceByKey((a, b) -> {
a.addAll(b);
return a;
});
First, you map to convert the value into a list of longs. Then reduceByKey and combine the lists using addAll method on arraylist.

Why does flatmapping and collecting a list of treesets return an object?

I am trying to put all the values treeset elements of a list with treesets into a linkedHashSet. This list of treesets is returned by the values() method of a TreeMap<String, TreeSet>. The code looks like this:
Map<String, TreeSet> sortedByMonthAndVarietyNameMap = new HashMap<>();
sortedByMonthAndVarietyNameMap.values().stream().flatMap(monthList -> monthList.stream()).collect(Collectors.toCollection(LinkedHashSet::new));
This should be returning a LinkedHashSet with all the elements of the flatmapped treesets. But in reality it returns an object of type Object.
Why is this happening? Can someone explain what i'm doing wrong?
The TreeSet is not fully typed:
Map<String, TreeSet<Integer>> sortedByMonthAndVarietyNameMap = new HashMap<>();
LinkedHashSet<Integer> result = sortedByMonthAndVarietyNameMap.values().stream()
.flatMap(monthList -> monthList.stream())
.collect(Collectors.toCollection(LinkedHashSet::new));
Is this what you wish?
LinkedHashSet<TreeSet> collect = sortedByMonthAndVarietyNameMap
.values()
.stream()
.flatMap(Stream::of)
.collect(Collectors.toCollection(LinkedHashSet::new));
P.S. This data conversion looks strange. Perhaps you could describe your case in more details?
As you have provided the constructor reference of LinkedHashSet without specifying the type.
https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.13

use stream to sum all values from array stored in map

I have a map which looks like this:
Map<String,String[]> urlFormEncoded = new HashMap<String,String[]>();
and I would like to sum all values stored in String[] arrays as a double value
I tried something like this:
double requestAmount = urlFormEncoded.entrySet().stream().mapToDouble(k -> Arrays.stream(k.getValue()).).sum();
but unfortunately I don't know how to convert this String[] to value :(
I would like to do this using streams and lambda expressions
The first step would be to convert each String[] as a DoubleStream.
Arrays.stream(arr).mapToDouble(Double::valueOf)
Then you have to flatMap those streams to get a single DoubleStream will all the double values.
.flatMapToDouble(arr -> Arrays.stream(arr).mapToDouble(Double::valueOf))
So you end up with:
double requestAmount =
urlFormEncoded.values()
.stream()
.flatMapToDouble(arr -> Arrays.stream(arr).mapToDouble(Double::valueOf))
.sum();
Note that you don't need to use the entrySet() if you plan to work only on the values, you can directly use values().

Get 3 highest values from Map<String,String>

I have a Map<String,String> which has entries like "User1","43". Now I want a "Top 3" of the highest values.
It would be easier with a Map<String,Integer>, but due to technical limitations I can just grab the Map as a <String,String>.
What's the most efficient way to convert a <String,String> map to a <String,Int> one and then sort it?
To convert from <String, String> to <String, Integer> you can use:
Map<String, Integer> treemap = new HashMap<String, Integer>();
for (Entry<String, String> entry : entries) {
treemap.put(entry.getKey(), Integer.parseInt(entry.getValue()));
}
However, then you will have to iterate the Map again. If you don't need the whole map, but rather just the top 3, then you can simply iterate the entries and get the top three by comparison.
Or you can reverse the key and value and use a TreeMap<Integer, String> with a Comparator, if you need both the top elements and the whole data.
There are a few ways:
Create SortedMap, e.g. TreeMap with a custom -anonymous- Comparator which performs comparisons by looking up the keys it gets in the compare() method call against the values in the original map.
Populate it with all key/value entries in the original through addAll() method.
Watch the map being sorted by value.
Grab the head/tail (depending on how your comparator sorts)
Similar to above:
Create a TreeSet of keys with a custom comparator as above...
Populate it with the keySet() of your original map.
Grab the head/tail set of the keys.
Create a new Map from those keys and value from the original map...
You could just put the values in a List and sort it:
ArrayList<Integer> highest = new ArrayList<Integer>();
for (String value : map.values()) {
highest.add(Integer.parseInt(value));
}
Collections.sort(highest);
for(int i = highest.size() - 1; i >=0 && i > highest.size()-4; i--){
System.out.println(highest.get(i));
}
If the map is very large it might be better to iterate through it and only select the 3 highest values without sorting the whole list.
You could iterate through the values of the Map (with Map.values()), converting each to an Integer (with Integer.getInteger(String s)), and keeping track of the top 3 you see.
Or, you could do as above but instead of keeping track of the top 3, make a LinkedList and insert each Integer at the correct place (traverse the LinkedList until you find where the Integer should be inserted).

Categories