Grouping similar items using hashmap - java

I have a input like this
0 [0.327097, 0.326998, 0.0]
0 [1.056364, 0.601873, 0.0]
0 [1.273154, 1.656441, 0.0]
1 [1.48469, 0.095074, 0.0]
1 [1.061504, -0.768175, 1.0]
i need to sort them as
0 : [ [0.327097, 0.326998, 0.0] ,[1.056364, 0.601873, 0.0], [1.273154, 1.656441, 0.0]]
1 : [ [1.48469, 0.095074, 0.0], [1.061504, -0.768175, 1.0]]
I did like this ..
but i am not getting the same output.my output is getting repeated.
Can u pls help me out...
Map<String, Collection<String>> groupMap = new HashMap<String, Collection<String>>();
String[] subparts = finalline.split("\\[");
String groupKey;
String value;
if (subparts.length == 1) {
groupKey = null;
value = subparts[0];
}
else if (subparts.length == 2) {
groupKey = subparts[0];
value = subparts[1];
}
else {
throw new IllegalArgumentException("Can not parse string");
}
Collection<String> groupContents = groupMap.get(groupKey);
if (groupContents == null) {
groupMap.put(groupKey, groupContents = new ArrayList<String>());
}
groupContents.add(value);
}

The value of the groupMap map is another collection, so you can iterate through that collection within the outer loop as given below
Map<String, Collection<String>> groupMap = new HashMap<String, Collection<String>>();
for(String key : groupMap.keySet()){
System.out.println("Key: " + key);
Collection<String> values = groupMap.get(key);
for(String value : values){
System.out.println("value: " + value);
}
}

Map<String, Collection<String>> groupMap = new HashMap<String, Collection<String>>();
for (String s : groupMap.keySet()) {
for (String s1 : groupMap.get(s)) {
System.out.println(s1);
}
}
A collection within a collection just means nested loops--just like with a 2D array.

I'd suggest using a HashMultimap from "Guava" instead.
It helps make it easy to handle a mapping from keys to multiple values and is a general way to associate keys with arbitrarily many values.
Here's an example.
Multimap<String, String> map = HashMultimap.create();
map.put("1", "a");
map.put("1", "b");
map.put("2", "c");
map.put("2", "d");
And now you can use the "values()" view to iterate over the values in the map.
for(String value : map.values()) {
System.out.println(value);
}
This will give you
a
b
c
d
Or if you want the key along with the value, then you can use the "entries()" view.
for(Map.Entry<String, String> entry : map.entries()) {
System.out.println("Key: " + entry.getKey() + " Value : " + entry.getValue());
}
This will give you
Key: 1 Value : a
Key: 1 Value : b
Key: 2 Value : c
Key: 2 Value : d
And if you're looking for a plain old java simple solution
Map<String, List<String>> map = new HashMap<String, List<String>>();
// ... Some code to put values in the map
for(String key : map.keySet()){
System.out.println("\nKey: " + key);
List<String> values = map.get(key);
for(String value : values) {
System.out.println("Value: " + value);
}
}

The best and most efficient way to iterate over a map's entries is:
Map<String, Collection<String>> map;
for (Map.Entry<String, Collection<String>> entry : map.entrySet()) {
System.out.print(entry.getKey()+":");
for (String str : entry.getValue())
System.out.println(str);
}
This code will produce the output you requested.
Note that at no point are the keys looked up. When you iterate over the entry set, you have direct access to both the (typed) key and (typed) value.

The most efficient way to loop over the entries in your Map is as follows:
Map<String, Collection<String>> groupMap = new HashMap<String, Collection<String>>();
for (Map.Entry<String, Collection<String>> entry : map.entrySet()) {
System.out.println("Key: "+entry.getKey());
for (String val : values) {
System.out.printlnln("Value: "+entry.getValue());
}
}

Related

Printing a Map with a nested Map

I have a Map of the following kind:
HashMap<String, Map<String, Integer>> resultMap = new HashMap<>();
Where String(Key) = Website address;
Map<String,Integer> = String(key) -search word, Integer(value) - counter for found words.
How to print the Map correctly so that it looks like this:
webSite1 - randomWord = 30, randomWord2 = 15, randomWord3 = 0
webSite2 - randomWord = 9, randomWord2 = 8, randomWord3 = 1
Thanks in advance for any ideas!
Map has simple iterator forEach((key, value) -> your_consumer), and the entries in the nested map may be converted into strings joined using Collectors.joining, so printing may be done as follows:
resultMap.forEach((k, v) ->
System.out.println(k + " - " +
v.entrySet().stream()
.map(e -> e.getKey() + "=" + e.getValue())
.collect(Collectors.joining(", "))
);
If I've correctly understood you:
In the outer loop, you should iterate the nested maps (as values),
and in the internal loop(s) you can finally iterate keys and values of the nested map.
HashMap<String, Map<String, Integer>> map = new HashMap<>();
for (Map<String, Integer> nestedMap : map.values())
{
for (String key : nestedMap.keySet()) {
// some actions here
}
for (Integer value : nestedMap.values()) {
// some actions here
}
}

Invert Map | Values ---> Keys

I want to be able to inverse a given HashMap that has multiple keys can point to the same value.
HashMap<String, String> cities = new HashMap<String, String>();
cities.put("Manchester", "UK");
cities.put("London", "UK");
static HashMap<String, String> inverseMap(HashMap map) {
// something that has "UK" point to both "Manchester" and "London"
// if it can be done without using any special Java 8 feature, that would be great
}
I am unsure where to start.
Do it like this. Basically, it employs a merge function which concatenates values for a duplicate key.
Create a new map
Use the values of the old map for the keys to the new
If the new map does not have a value for the key, put the value in the new map
Otherwise, concatenate the value to the old value for that key
HashMap<String, String> cities = new HashMap<String, String>();
cities.put("Manchester", "UK");
cities.put("London", "UK");
cities.put("New York", "US");
cities.put("Chicago", "US");
Map<String,String> inverted = new HashMap<>();
for (String key : cities.keySet()) {
String newKey = cities.get(key);
String value = inverted.get(newKey);
if (value == null) {
inverted.put(newKey, key);
} else {
value = value + ", " + key;
inverted.put(newKey, value);
}
}
for (Entry<String,String> e : inverted.entrySet()) {
System.out.println(e.getKey() + " -> " + e.getValue());
}
It prints
UK -> Manchester, London
US -> New York, Chicago
Since you didn't specify how to handle duplicate keys. I could also have stored it in a Map<String,List<String>>
Is this what you're looking for?
Map<String, String> cities = new HashMap<>();
cities.put("Manchester", "UK");
cities.put("London", "UK");
Map<String, List<String>> reverseMap = new HashMap<>();
for (Entry<String, String> entry : cities.entrySet()) {
List<String> list = reverseMap.get(entry.getValue());
if (list == null) {
list = new ArrayList<>();
reverseMap.put(entry.getValue(), list);
}
list.add(entry.getKey());
}
System.out.println(reverseMap);
As multiple keys can contain the same value, you will have to be able to store multiple values per key in the inversed Map. I recommend using a Set as a value for this.
Create a map that can save a Set of Strings as values
Iterate through the original map
If the country is not found in the new map, create an entry there
Add the city to the map
This should also work with Java 7 without dependencies.
static HashMap<String, Set<String>> inverseMap(HashMap<String,String> map) {
HashMap<String,Set<String>> inversed=new HashMap<>();
for(Map.Entry<String,String> entry:map.entrySet()){
if(!inversed.containsKey(entry.getValue())){
inversed.put(entry.getValue(),new HashSet<>());
}
inversed.get(entry.getValue()).add(entry.getKey());
}
return inversed;
}
{Manchester=UK,London=UK} would turn into {UK={Manchester,London}} (order may differ).
You can look at MultiMap. It allows mapping of a single key to multiple values.
This is something has been implemented in both Google Guava
https://guava.dev/releases/19.0/api/docs/com/google/common/collect/Multimap.html
ListMultimap<String, String> multimap = ArrayListMultimap.create();
for (President pres : US_PRESIDENTS_IN_ORDER) {
multimap.put(pres.firstName(), pres.lastName());
}
for (String firstName : multimap.keySet()) {
List<String> lastNames = multimap.get(firstName);
out.println(firstName + ": " + lastNames);
}
... produces output such as:
Zachary: [Taylor]
John: [Adams, Adams, Tyler, Kennedy] // Remember, Quincy!
George: [Washington, Bush, Bush]
Grover: [Cleveland, Cleveland] // Two, non-consecutive terms, rep'ing NJ!
As in Apache Commons Collections
https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/MultiValuedMap.html
MultiValuedMap<K, String> map = new MultiValuedHashMap<K, String>();
map.put(key, "A");
map.put(key, "B");
map.put(key, "C");
Collection<String> coll = map.get(key);
coll will be a collection containing "A", "B", "C".
You can iterate over the entry set of your original map and use the values (country code) as key and add each key (cities) to a list:
static HashMap<String, List<String>> inverseMap(HashMap<String, String> map) {
HashMap<String, List<String>> countryToCity = new HashMap<>();
for(Map.Entry<String,String> entry: map.entrySet()){
countryToCity.computeIfAbsent(entry.getValue(), k -> new ArrayList<>()).add(entry.getKey());
}
return countryToCity;
}

How to efficiently iterate a Multimap?

I have the following multimap:
Multimap<String,Multimap<String,Integer>> map = ArrayListMultimap.create();
I need to iterate it, but I am stuck.
How should I iterate it?
It looks like you are using google guava multimap and the create method of the class ArrayListMultimap to create it.
You can iterate through your multimap and your inner multimap like this:
package com.test.java;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
public class Main {
#SuppressWarnings("unchecked")
public static void main(String[] args) {
Multimap<String, Multimap<String,Integer>> map = ArrayListMultimap.create();
Multimap<String,Integer> m = ArrayListMultimap.create();
//put some values
m.put("value1", 1);
m.put("value2", 2);
m.put("value3", 3);
map.put("one", m);
for (Object value1 : map.values()) {
for (Object value2 : ((Multimap<String,Integer>)value1).values()) {
System.out.println((Integer)value2);
}
}
}
}
Output:
2
1
3
Note:
If you want to have a deterministic iteration order, use LinkedListMultimap:
Example:
LinkedListMultimap<String, LinkedListMultimap<String,Integer>> map = LinkedListMultimap.create();
LinkedListMultimap<String,Integer> m = LinkedListMultimap.create();
//put some values
m.put("value1", 1);
m.put("value2", 2);
m.put("value3", 3);
map.put("one", m);
for (Object value1 : map.values()) {
for (Object value2 : ((LinkedListMultimap<String,Integer>)value1).values()) {
System.out.println((Integer)value2);
}
}
Output:
1
2
3
Map<String, Multimap<String>> map = multimap.asMap();
System.out.println("Multimap as a map");
for (Map.Entry<String, Multimap<String>> entry : map.entrySet()) {
String key = entry.getKey();
Multimap<String> value = multimap.get("lower");
System.out.println(key + ":" + value);
}
please try it out.
my example
ListMultimap<Long, Long> items = elasticResult.getResult();
for (Long key : items.keySet()) {
items.get(key).forEach(value -> {
// ... use key and value
});
}

Java - How to iterate over a hashmap of list of hashmap

I want to iterate over a hashmap of list of hashmap.
for example,
HashMap <String, List <HashMap<String, String> > >
How do I iterate over this map.
Please help me to find a solution.
You should probably look over your design, this sounds like something that could be structured in an easier way. Consider maybe breaking this collection up into classes.
But, in case you cannot change it now (or don't have the time), I'll offer a hand.
The easiest way is probably to break the iteration up in several steps:
Iterate over the inner HashMaps
Iterate over the lists
Iterate over the content in the inner HashMaps
Here's the basic code:
for( List<HashMap<String, String>> list : outer.values() ) {
for( HashMap<String, String> map : list ) {
for( String value : map.values() ) {
//Do something
}
}
}
Let us name your map.
HashMap<String, List<HashMap<String, String>>> map; //I'll assume it is initialized and filled with something.
for (String key : map.keySet()) {
for (HashMap<String, String> map2 : map.get(key)) {
for (String key2 : map2.keySet()) {
//do something
}
}
}
Another approach is to use nested loops through collections:
for (List<HashMap<String, String>> list : map.values()) {
for (HashMap<String, String> map2 : list) {
for (String veryInnerValue : map2.values()) {
//do something
}
}
}
The differ a bit. In case you don't need to know the key of the value, the second is better.
If you need to know key and value for each map :
Map<String, List<HashMap<String, String>>> myMap = new HashMap<String, List<HashMap<String, String>>>();
// loop for first map
for (Entry<String, List<HashMap<String, String>>> myMapEntry : myMap.entrySet()) {
System.out.println("myMap entry key" + myMapEntry.getKey() + ", key ");
// loop for list (value of entry)
for (HashMap<String, String> valueOfList : myMapEntry.getValue()) {
// loop for second map
for (Entry<String, String> entryOfMapOfList : valueOfList.entrySet()) {
System.out.println("key " + entryOfMapOfList.getKey() + " value " + entryOfMapOfList.getValue());
}
}
}

Recursively or iteratively retrieve key-value combinations from a HashMap

I want to retrieve k,v-pairs from a HashMap.
The entrys are like this:
a = 3,4
b = 5,6
and so on. I need combinations of these values.
a=3, b=5
a=3, b=6
a=4, b=5
a=4, b=6
I don't know how many keys and how many entrys the values have. With entrySet I can get the values but not combinations. It looks like recursion but how?
Here's my code:
HashMap<String, String[]> map = new HashMap<String, String[]>();
BufferedReader file = new BufferedReader(new FileReader("test.txt"));
String str;
while ((str = file.readLine()) != null) {
// ... logic
map.put(key, value);
}
System.out.println("number of keys: " + map.size());
for (Map.Entry<String, String[]> entry : map.entrySet()) {
for (String value : entry.getValue()) {
System.out.println(entry.getKey() + ": " + value);
}
}
file.close();
You can try the following code:
public void mapPermute(Map<String, String[]> map, String currentPermutation) {
String key = map.keySet().iterator().next(); // get the topmost key
// base case
if (map.size() == 1) {
for (String value : map.get(key)) {
System.out.println(currentPermutation + key + "=" + value);
}
} else {
// recursive case
Map<String, String[]> subMap = new HashMap<String, String[]>(map);
for (String value : subMap.remove(key)) {
mapPermute(subMap, currentPermutation + key + "=" + value + ", ");
}
}
}
No guarantees on memory efficiency or speed. If you want to preserve the order of the keys in the map, you will have to pass in a TreeMap and change the code to use a TreeMap under the recursive case.
As the base case suggests, I'm assuming you have at least one entry in your map.
You can obtain a Cartesian product of map key-value combinations using a map and reduce approach.
Try it online!
Map<String, String[]> map = Map.of(
"a", new String[]{"3", "4"},
"b", new String[]{"5", "6"});
List<Map<String, String>> comb = map.entrySet().stream()
// Stream<List<Map<String,String>>>
.map(e -> Arrays.stream(e.getValue())
.map(v -> Map.of(e.getKey(), v))
.collect(Collectors.toList()))
// summation of pairs of list into a single list
.reduce((list1, list2) -> list1.stream()
// combinations of inner maps
.flatMap(map1 -> list2.stream()
// concatenate into a single map
.map(map2 -> {
Map<String, String> m = new HashMap<>();
m.putAll(map1);
m.putAll(map2);
return m;
}))
// list of combinations
.collect(Collectors.toList()))
// otherwise, an empty list
.orElse(Collections.emptyList());
// output, order may vary
comb.forEach(System.out::println);
Output, order may vary:
{a=3, b=5}
{a=3, b=6}
{a=4, b=5}
{a=4, b=6}
See also: Cartesian product of map values
It looks to me like you really want a MultiMap. In particular, ArrayListMultimap allows duplicate entries:
ArrayListMultimap<String, String> map = ArrayListMultimap.create();
for each line in file:
parse key k
for each value in line:
parse value v
map.put(k, v);
for (Map.Entry<String, String> entry : map.entries()) {
String key = entry.getKey();
String value = entry.getValue();
}
If you want a cartesian product of maps, you could compute that directly using recursion, or you could iterate over the maps: create a list of iterators and iterate odometer-style; when iterator N reaches its end, advance iterator N+1 and reset iterators 1..N.
Just poked around and found this SO question.
So I'd recommend you use guava's Sets.cartesianProduct for the cartesian product. Here's my poking around code, which you could adapt to your input logic:
String key1 = "a";
Set<Integer> values1 = Sets.newLinkedHashSet(Arrays.asList(1, 2, 3, 4));
String key2 = "b";
Set<Integer> values2 = Sets.newLinkedHashSet(Arrays.asList(5, 6, 7));
String key3 = "c";
Set<Integer> values3 = Sets.newLinkedHashSet(Arrays.asList(8, 9));
List<String> keys = Arrays.asList(key1, key2, key3);
Set<List<Integer>> product = Sets.cartesianProduct(values1, values2, values3);
for (List<Integer> values : product) {
for (int i = 0; i < keys.size(); ++i) {
String key = keys.get(i);
int value = values.get(i);
System.out.print(key + "=" + value + "; ");
}
System.out.println();
}

Categories