How to use Map, TreeMap with List in Java? - java

How can I transform the following data result
[a={x=0, y=43, z=57}, b={x=1, y=90, z=9}, c={x=1, y=83, z=16}]
into
{x=[0,1,1], y=[43,90,83], z=[57,9,16]}
using Map and Treemap.
Basically, I am iterating over a,b,c.. then while reading its values I want to sort them by Key(x),values(0,1,1), Key(y),values(43,90,83) and so on.
Thanks a lot for your help.

Obviously
Map<String, Map<String, Integer>> mapOfMaps = ...
TreeMap<String, List<Integer>> series = mapOfMaps.values().stream()
.map(Map::entrySet)
.flatMap(Set::stream)
.collect(Collectors.groupingBy(Entry::getKey, TreeMap::new,
Collectors.mapping(Entry::getValue, Collectors.toList())));
http://ideone.com/LHYhE7

You cannot transform data using a Map. You organize 'transformed data' into a map. Organizing the data can be done with methods exposed in String class.
It is safe to assume that the following is a String at your end.
[a={x=0, y=43, z=57}, b={x=1, y=90, z=9}, c={x=1, y=83, z=16}]
Use String API to get hold of each of the set content. http://docs.oracle.com/javase/7/docs/api/java/lang/String.html You can look at methods like indexOf or split or substring. This helps you divide the string into chunks of {.....}.
You now have to traverse and identify the integer values for x,y,z and as you find them, you can add them to a List. Example: ArrayList.
Finally, you add the string x,y,z and their corresponding ArrayLists to a TreeMap.

Related

Best way to compare bunch of Constant Strings (keys) with a Map

So, I have a Map (String, String) which I receive this map can have about 600-800 entries. My task is to retrieve only about 60-120 (based on some logic) of those pairs based on the keys (constant strings).
Right now I have created a List of the required Keys, I am iterating the Map I receive and pulling out required pairs into another Map and passing it on. This works, but the code looks horrible.
There surely has to be a better way of doing this. Any suggestions?
I thought of using contains instead of matching keys, but my requirement is for exact matches. Yes, I read about using RegEx for exact matches, so that can be used as a last resort.
What I need help with:
1. Better way to store required keys than having them in a List. This list of keys are going to be a constant. Having a list of 60-120 strings hardcoded into a List looks horrible.
2. Fastest (time) way to compare the said list and pull out required pairs.
My code:
List <String> keysToCheck = new ArrayList<String>();
keysToCheck.add("attrib1");
...
keysToCheck.add("attribN");
Map<String, String> newMap = new HashMap<String, String>();
for (String key : keysToCheck) {
if(mapRcvd.containsKey(key)) {
newMap.put(key, mapRcvd.get(key));
}
}
I am looking for solutions which would be quicker, as this would be a very small part of a larger application. I am good with having to write a lot of code to achieve that.
You can store all constant keys in a file, where each line contains one key. Then you can get all required keys like:
List<String> requiredKeys = Files.lines(Paths.get(PATH_TO_FILE_WITH_KEYS))
.collect(Collectors.toList());
Now get map with required keys using stream filter method:
Map<String, String> collect = mapRcvd.entrySet().stream() // get stream of map entries
.filter(entry -> requiredKeys.contains(entry.getKey())) // filter only such entries which has required key
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); // collect all filtered entries into new map
More about Collectors.toMap, javadoc
Update: while getting map with required keys may seem more compact, the for-loop with containsKey method in your example is faster than contains. You should probably use the advice #Holger left in the comments

How to iterate and remove keys from Map<String , Map<String, Set<String>>>

I am having map this way,
Map<String, Map<String, Set<String>>> sampleMap = new Map<String, Map<String, Set<String>>>();
and the data in this map would be this way,
sampleMap={2014={A=[1, 2], B=[3], 2015={A=[1,2], B=[1,2], 2016={A=[1,2], B=[3,4]}};
I want to remove the key's from the map based on this input: List<String> filter; with values this way,
filterArray : [2014, 2015]
i.e, first iterate through arraylist values one by one, verify if the arraylist value matches with any of the key in Hashmap.
if key is matched ignore it.
if key is not matched, I just want to remove that key from the map.
i.e, I always want to keep only matched keys in map, comparing with the input value passed.
In this case, as I have arraylist values this way,[2014,2015],
2014,2015 keys only to be in my map. So,
Data to be before removal:
sampleMap={2014={A=[1, 2], B=[3], 2015={A=[1,2], B=[1,2], 2016={A=[1,2], B=[3,4]}};
Data to be after removel:
sampleMap={2014={A=[1, 2], B=[3], 2015={A=[1,2], B=[1,2]}};
I tried this way, However I just want to know is this is the correct approch, or is it is prone to any of the exceptions?
Iterator<Map.Entry<String , Map<String, Set<String>>>> iter = sampleMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String , Map<String, Set<String>>> entry = iter.next();
logger.info("Keys : " + entry.getKey());
if (filterArray.equalsIgnoreCase(entry.getKey())) {
iter.remove();
}
}
Use retainAll() on the keySet:
map.keySet().retainAll(list);
Seems reasonable. I might have a couple pieces of advice.
First of all, whenever I see nested collections I always wonder if there should be a class or two in there. If this is a one-time task then don't worry about it, but if you want to reuse this code you might want to think about creating a class for your inner map/set... but if it's really this simple then it's no big deal.
Secondly if you are using Java 8, using a list comprehension for filtering would perform better (Because it would automatically thread your compares) and would be cleaner. I can give you the groovy solution for what you are trying to do, but I'm not familiar enough with java 8 list comprehensions to do it correctly.
def filteredStructure=structure.findAll{entry->entry.key.equalsIgnoreCase("2014") || entry.key.equalsIgnoreCase("2015"))
The java version should be really similar.

Concatenate the String values of all Maps in a List

I am trying to adapt Lambda features, however few struggles here and there.
List<Map<String, String>> list = new LinkedList<>();
Map<String, String> map = new HashMap<>();
map.put("data1", "12345");
map.put("data2", "45678");
list.add(map);
I just want to print the values in comma separated format like 12345,45678
So here goes my trial
list.stream().map(Map::values).collect(Collectors.toList()) //Collectors.joining(",")
and the output is [[12345,45678]]. It means, there's a list and inside list it's creating the comma separated value at 0 index. I do understand why it's doing though.
But I didn't get through how to extract my desired result unless I call .get(0) in the end of that expression.
Any help/some more insights on how to use lambdas better will be helpful
Try this :
list.stream()
.map(Map::values)
.flatMap(Collection::stream)
.collect(Collectors.joining(","))
The flatMap method flattens out a Collection<Stream<String>> into a single Stream<String>.
Alternatively, you can try what #Holger suggested in the comments.
Note that since you are using a Map, there is no guarantee that the order will be preserved. You might see the output as 45678,12345 at your end. If you wish to preserve the order, you can use a LinkedHashMap instead of a HashMap.

How to perform a group by (sql) in Java

I have a text file which looks like this:
code appearance
----------------
j4t8 1
fj89 3
pf6n 1
j4t8 5
And I want to sort by the codes which appear the most. As you can see (and since I want to perform a group by) there are duplicate codes, so using HashMap would be a problem (duplicate keys). Any ideas?
don't know if this is the best solution but you could create a map of a list like this:
Map<String, List<Integer>> map = new HahsMap<String, List<Integer>>();
if(map.contains.(key))
{
map.get(key).add(new_appearance_value);
}
else
{
List<Integer> app = new ArrayList<Integer>();
app.add(new_appearance_value);
map.put(key, app);
}
Where the map key would be the code and the values of appearance would go into the list.
Note: to determine which code has more appearances just check for the size of the list of each code.
You can use
HashMap map = new HashMap<String, List<Integer>>();
The appearances will be stored in a list associated with every code.
Then given a code you just retrieve the list of integers and iterate over it.
You need a Collection of Pair objects. Each pair holds the code and the appearance. You then sort the collection using a Comparator, which only compares the appearance in each Pair object, and disregards the code.
The Commons Collections MultiValueMap can be used to decorate another map, allowing it to have more than one value for a key.

How to get all the entries from a LinkedHashMap in Java?

I am using String object as the key to a linkedhashmap.
How can I get all the entries in the LinkedHashMap?
You have three options that depend on whether you need just keys, just values or both
Set<String> keys = yourMap.keySet();
Collection<YourValueClass> values = yourMap.values();
Set<Map.Entry<String,YourValueClass>> pairs = yourMap.entrySet();
then you can easily iterate over them if you need. Actually all of them allow iterating using a simple foreach loop:
for (Map.Entry<String,YourClassValue> e : yourMap.entrySet())
// do something
You can use the entrySet method, which returns a set containing the key-value pairs in your map.

Categories