A hashmap inside of a hasmap print out - java

I am trying to print out a hashmap that contains A character as the key and the value as another hashmap with Integer and Double
I have this so far but isn't working.
HashMap<Character, Map<Integer, Double>> MapInsideOfAMap = calc.MapInAMap(abc);
for (Entry<Character, Map<Integer, Double>> outer : MapInsideOfAMap.entrySet()) {
System.out.println("Char: " + outer.getKey() + "\n");
for (Map.Entry<Character, Map<Integer, Double> inner : MapInsideOfAMap.getValue().entrySet()) {
System.out.println("int = " + inner.getKey() + ", double = " + inner.getValue());
}
}

Your code should be like this,
for (Entry<Character, Map<Integer, Double>> outer : MapInsideOfAMap.entrySet()) {
System.out.println("Char: " + outer.getKey() + "\n");
for (Entry<Integer, Double> inner : MapInsideOfAMap.get(outer.getKey()).entrySet()) {
System.out.println("int = " + inner.getKey() + ", double = " + inner.getValue());
}
}
Okay, I understood what you were trying to do,
since you already got Outer map entry, you don't have to again use outer map reference, you can directly do like this,
for (Entry<Character, Map<Integer, Double>> outer : MapInsideOfAMap.entrySet()) {
System.out.println("Char: " + outer.getKey() + "\n");
for (Entry<Integer, Double> inner : outer.getValue().entrySet()) {
System.out.println("int = " + inner.getKey() + ", double = " + inner.getValue());
}
}

Let's assume your map looks like this:
Map <Character, Map<Integer, Double>> MapInsideOfAMap = new HashMap();
then you can print your map like this:
for (Entry<Character, Map<Integer, Double>> outer : MapInsideOfAMap.entrySet()) {
System.out.println("Char: " + outer.getKey() + "\n");
HashMap<Integer, Double> innermap = MapInsideOfAMap.get(outer.getKey());
for (Map.Entry<Integer, Double> innerEntry : innermap.entrySet()) {
System.out.println("int = " + innerEntry.getKey() + ", double = " + innerEntry.getValue());
}
}

If you need just to see map key/values, use System.out.println
Map AbstractMap.toString knows how to print itself in a nice and readable way.
Map<Character, Map<Integer, Double>> map = new HashMap<>();
map.put('A', new HashMap<>());
map.get('A').put(1, 0.01);
map.put('B', new HashMap<>());
map.get('B').put(2, 0.02);
System.out.println(map);
prints out this :
{A={1=0.01}, B={2=0.02}}

To simply print out the whole map of maps:
System.out.println(mapInsideOfAMap);
Now, if you want to iterate your outer and inner maps and print their key/value pairs you could use the Map.forEach method:
mapInsideOfAMap.forEach((outerKey, outerValue) -> {
System.out.println("Char: " + outerKey + "\n");
outerValue.forEach((innerKey, innerValue) ->
System.out.println("int = " + innerKey + ", double = " + innerValue));
});

public static void main(String z[]) {
Map<Character, Map<Integer, Double>> MapInsideOfAMap = getmapOfMap();
for (Entry<Character, Map<Integer, Double>> outer : MapInsideOfAMap.entrySet()) {
System.out.println("Char: " + outer.getKey() + "\n");
Map<Integer, Double> mapInner = MapInsideOfAMap.get(outer.getKey());
for (Map.Entry<Integer, Double> inner : mapInner.entrySet()) {
System.out.println(inner.getKey() +":"+ mapInner.get(inner.getKey()));
}
}
}
private static Map getmapOfMap() {
char[] chArr = {'a','b','c','d','e','f','g','h','i','j','k'};
HashMap<Character, Map<Integer, Double>> mapInsideOfAMap = new HashMap<Character, Map<Integer, Double>>();
for(char ch:chArr) {
mapInsideOfAMap.put(ch, getInnterMap());
}
return mapInsideOfAMap;
}
private static Map getInnterMap() {
Map<Integer, Double> map = new HashMap<>();
for(int i=1000;i<1010;i++) {
map.put(i, new Double(String.valueOf(i)));
}
return map;
}

In the second for-loop, you need to access the Map you get as a value from the outer loop.
You also need to change the type of the Entry in the second loop.
Try this code:
for (Entry<Character, Map<Integer, Double>> outer : MapInsideOfAMap.entrySet()) {
System.out.println("Key: " + outer.getKey() + "\n");
for (Entry<Integer, Double> inner : outer.getValue().entrySet()) {
System.out.println("Key = " + inner.getKey() + ", Value = " + inner.getValue());
}
}

But the complexity of the structure is probably redundant.
public static void print(char keyData, Map<Character, Map<Integer, Double>> fromData) {
System.out.println("print: " + get(keyData, fromData));
}
public static Map<Integer, Double> get(char keyData, Map<Character, Map<Integer, Double>> fromData) {
for (Map.Entry<Character, Map<Integer, Double>> entry : fromData.entrySet()) {
Character key = entry.getKey();
if(key.equals(keyData))
return entry.getValue();
}
return Collections.emptyMap();
}

Related

How can I duplicate an HashMap with duplicate values

I need to create new HashMaps that contain only the duplicate values of my first HashMap :
Original map: {Player1=Hello, Player2=Hi, Player3=Hi, Player4=Hello, Player5=Hello}
For the outputs, I want to get :
Hello map: {Player1=Hello,Player4=Hello, Player5=Hello}
Hi map: {Player2=Hi, Player3=Hi}
What is best way to do?
If you are using Java8+ you can use stream, with groupingBy and toMap like so :
Map<String, Map<String, String>> collect = map.entrySet().stream()
.collect(Collectors.groupingBy(Map.Entry::getValue,
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
For e simple map, your outputs can be :
Hi - {Player2=Hi, Player3=Hi}
Hello - {Player5=Hello, Player1=Hello, Player4=Hello}
Ideone demo
class Player {
private String name;
private int id;
public Player(int id) {
this.id = id;
this.name = "Player " + id;
}
#Override
public int hashCode() {
return this.id;
}
#Override
public String toString() {
return this.name;
}
}
Player[] players = new Player[5];
IntStream.range(0, players.length).forEach(i -> players[i] = new Player(i + 1));
// -------------------------------------------------------------------------
HashMap<Player, String> original = new HashMap<>();
original.put(players[0], "Hello");
original.put(players[1], "Hi");
original.put(players[2], "Hi");
original.put(players[3], "Hello");
original.put(players[4], "Hello");
HashMap<String, HashMap<Player, String>> duplicates = new HashMap<>();
original.keySet().stream().forEach(key -> {
String value = original.get(key);
HashMap<Player, String> duplicate = duplicates.get(value);
if (duplicate == null) {
duplicate = new HashMap<>();
duplicates.put(value, duplicate);
}
duplicate.put(key, value);
});
System.out.println("Original: " + original);
duplicates.forEach((key, value) -> {
System.out.println(key + ": " + value);
});
//
Original: {Player 1=Hello, Player 2=Hi, Player 3=Hi, Player 4=Hello, Player 5=Hello}
Hi: {Player 2=Hi, Player 3=Hi}
Hello: {Player 1=Hello, Player 4=Hello, Player 5=Hello}

How to "print" a HashMap in a Hashmap in Java/Android

I want to "print" a Hashmap<String, Integer> (let's say Alpha) in a Hashmap<String, Hashmap<String, Integer>> (Beta) and I say "print" because I don't want the "printed" Alpha to change when I re-use Alpha.
For example:
class scratch_2 {
public static void main(String[] args) {
HashMap<String, Integer> Alpha = new HashMap<>();
HashMap<String, HashMap<String, Integer>> Beta = new HashMap<>();
Beta.put("A1", Alpha);
Beta.put("B2", Alpha);
Alpha.put("A", 1);
Alpha.put("B", 2);
System.out.println(Beta); --->print1
Alpha.clear();
System.out.println(Beta); ---->print2
}
}
Result of print1: {A1={A=1, B=2}, B2={A=1, B=2}}
Result of print2: {A1={}, B2={}}
How to set the Beta.put() so that when Alpha is cleared, Beta remains the same?
Here is what you can do to reset a nested HashMap. The value is removed on line 22 and then added back as a new inner hashmap instance. Again, I loop through containingMap and the innerMap getting each map. Once I have a value to reset I call the reset function.
import java.util.*;
import java.lang.*;
public class Collections {
public HashMap<String, HashMap<String, Integer>>
createMap(String beta, String alpha, int m, HashMap<String,
Integer> innerStructure, HashMap<String, HashMap<String,
Integer>> containingStructure) {
while(m>0) {
innerStructure.put(beta, m);
m--;
}
containingStructure.put(alpha, innerStructure);
return containingStructure;
}
public void reset(HashMap<String, HashMap<String, Integer>>
map, int x) {
HashMap<String, Integer> betaMap = new HashMap<String, Integer>();
for(Map.Entry<String,HashMap<String,Integer>> entry: map.entrySet()) {
System.out.println("Key before is:" + entry.getKey());
if(entry.getValue() instanceof Map) {
for(Map.Entry<String, Integer> mapEntry: entry.getValue().entrySet()) {
if(mapEntry.getValue() == x) {
entry.getValue().remove(x);
map.put(entry.getKey(), betaMap);
}
}
}
}
}
public void print(HashMap<String, HashMap<String, Integer>> map) {
for(Map.Entry<String,HashMap<String,Integer>> entry: map.entrySet()) {
System.out.println("Key is:" + entry.getKey());
if(entry.getValue() instanceof Map) {
for(Map.Entry<String, Integer> mapEntry: entry.getValue().entrySet()) {
System.out.println(mapEntry.getKey());
}
}
}
}
public static void main(String[] args) {
Collections collections = new Collections();
HashMap<String, Integer> innerStructure = new HashMap<>();
HashMap<String, HashMap<String, Integer>> containingStructure = new HashMap<>();
containingStructure = collections.createMap("B1", "A1", 4, innerStructure, containingStructure);
collections.reset(containingStructure, 2);
collections.print(containingStructure);
}
}
It really doesn't change the Beta with put it is a matter of evaluating each entry and making sure it is a new HashMap type being used in it's place. I think this should help.
As #Andreas said, I should have created a new instance of Alpha by assigning it like Alpha = new HashMap<>(); when I no longer needed it. I can then re-use it without affecting Beta.

How to sort a TreeSet by Value?

I am pretty new to TreeMap and TreeSet and the likes and was wondering how to sort the data structures by value? I realise with a TreeSet you can sort it into alphabetical order automatically but I want it to order via value? Any idea on how to do this?
It currently prints like...
aaa: 29
aaahealthart: 30
ab: 23
abbey: 14
abdomin: 3
aberdeen: 29
aberdeenuni: 20
When I want it to print like...
aaahealthart: 30
aaa: 29
aberdeen: 29
ab: 23
aberdeenuni: 20
abbey: 14
abdomin: 3
Here is my method here...
ArrayList<String> fullBagOfWords = new ArrayList<String>();
public Map<String, Integer> frequencyOne;
public void termFrequency() throws FileNotFoundException{
Collections.sort(fullBagOfWords);
Set<String> unique = new TreeSet<String>(fullBagOfWords);
PrintWriter pw = new PrintWriter(new FileOutputStream(frequencyFile));
pw.println("Words in Tweets : Frequency of Words");
for (String key : unique) {
int frequency = Collections.frequency(fullBagOfWords, key);
System.out.println(key + ": " + frequency);
pw.println(key + ": " + frequency);
}
pw.close();
}
Thanks for all the help guys.
TreeMap orders by key, I don't think you can use the same implementation to sort by the value. But you can achieve the task with a slightly different approach:
public Map<String, Integer> countWords(List<String> words) {
Map<String, Integer> result = new Map<>();
for (String word : words) {
if (result.containsKey(word)) {
// the word is already in the map, increment the count
int count = result.get(word) + 1;
result.put(word, count);
} else {
result.put(word, 1);
}
}
return result;
}
Then you just need to sort the elements of the resulting map. You can do this in the following way:
public List<Map.Entry<String, Integer> sortMap(Map<String, Integer> map) {
List<Map.Entry<String, Integer> elements = new LinkedList<>(map.entrySet());
Collections.sort(elements, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2 ) {
return o1.getValue().compareTo(o2.getValue());
}
});
}
So you use the first method to count the word frequency and the second to sort by it.
You can create an ArrayList and store each entry in it like this:
ArrayList<Map.Entry<String, Integer> list = new new ArrayList(map.entrySet());
then you can sort the arrayList using a comparator that compares the entries by their value:
Collections.sort(list , new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2 ) {
return o1.getValue().compareTo(o2.getValue());
}
});
And then you can print the entries from the arrayList
Try something like this:
Set<Map.Entry<Integer, Integer>> sorted =
new TreeSet<Map.Entry<Integer, Integer>>(new Comparator<Map.Entry<Integer, Integer>> {
public int compare(Map.Entry<Integer, Integer> first, Map.Entry<Integer, Integer> second) {
return first.getValue().compareTo(second.getValue());
}
public boolean equals(Map.Entry<Integer, Integer> that) {
return this.equals(that);
}
});
That should give you what you want.

How to iterate a map from another map?

I have this Map where the key is an Integer and the value is another map. I want to know how to iterate through the second map.
private Map<Integer,Map<Integer,Integer>> transition = new HashMap<Integer, Map<Integer, Integer>>();
private Map<Integer,Map<Integer,Integer>> transition = new HashMap<Integer, Map<Integer, Integer>>();
for (Integer outerKey : transition.keySet()) {
Map<Integer, Integer> inner = transition.get(outerKey);
for (Integer innerKey : inner.keySet()) {
Integer value = inner.get(innerKey);
}
}
+1 #angel_navarro Another way is using entry set
Map<Integer, HashMap<Integer, Integer>> map = new HashMap<Integer, HashMap<Integer, Integer>>();
for (Map.Entry<Integer, HashMap<Integer, Integer>> entry : map.entrySet()) {
HashMap<Integer, Integer> submap = entry.getValue();
for (Map.Entry<Integer, Integer> sub_entry : submap.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = "
+ entry.getValue());
}
}
I like this idiom better:
for(Map.Entry<Integer,Map<Integer,Integer>> outer : transition.entrySet()){
Integer outerKey = outer.getKey();
for(Map.Entry<Integer,Integer> inner : outer.getValue().entrySet()){
Integer innerKey = inner.getKey();
Integer innerValue = inner.getValue();
}
}
By the way, I suggest you take a look at Guava's new collection types, e.g., Multimap, for alternatives to nested collections. Maybe they won't fit your use case today, but it's good to know they exist.
private Map<Integer,Map<Integer,Integer>> transition = new HashMap<Integer, Map<Integer, Integer>>();
for(Map.Entry<Integer,Map<Integer,Integer>> entryMap : transition.values())
{
final Integer outerKey = entryMap.getKey();
for (Map.Entry<Integer, Integer> entry : entryMap.getValue().entrySet())
{
final Integer innerKey = entry.getKey();
final Integer innerValue = entry.getValue();
}
}

Sorting a HashMap, while keeping duplicates

I'm trying to sort a HashMap in two ways. The default way: alphabetically by the value, the second way: numerically by the key, with the higher number being at the top. I have searched around but can't find anything on the subject, and what I do find, doesn't work. If it's not possible to sort both of them (I want the person with the highest key at the top, decreasing as people have lower keys, then alphabetically sort all of the rest (the people with 0 as their key).
Here's what I've tried so far:
private HashMap<String, Integer> userGains = new HashMap<String, Integer>();
public void sortGains(int skill, int user) {
userGains.put(users.get(user).getUsername(), users.get(user).getGainedExperience(skill));
HashMap<String, Integer> map = sortHashMap(userGains);
for (int i = 0; i < map.size(); i++) {
Application.getTrackerOutput().getOutputArea(skill).append(users.get(user).getUsername() + " gained " + map.get(users.get(user).getUsername()) + " experience in " + getSkillName(skill) + ".\n");
}
}
public LinkedHashMap<String, Integer> sortHashMap(HashMap<String, Integer> passedMap) {
List<String> mapKeys = new ArrayList<String>(passedMap.keySet());
List<Integer> mapValues = new ArrayList<Integer>(passedMap.values());
LinkedHashMap<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
Collections.sort(mapValues);
Collections.sort(mapKeys);
Iterator<Integer> it$ = mapValues.iterator();
while (it$.hasNext()) {
Object val = it$.next();
Iterator<String> keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
String comp1 = passedMap.get(key).toString();
String comp2 = val.toString();
if (comp1.equals(comp2)) {
passedMap.remove(key);
mapKeys.remove(key);
sortedMap.put((String) key, (Integer) val);
break;
}
}
}
return sortedMap;
}
Since you cannot run that here is an SSCCE:
private HashMap<String, Integer> userGains = new HashMap<String, Integer>();
private Object[][] testUsers = { { "Test user", 15 }, { "Test", 25 }, { "Hello", 11 }, { "I'm a user", 21 }, { "No you're not!", 14 }, { "Yes I am!", 45 }, { "Oh, okay. Sorry about the confusion.", 0 }, { "It's quite alright.", 0 } };
public static void main(String[] arguments) {
new Sorting().sortGains();
}
public void sortGains() {
for (Object[] test : testUsers) {
userGains.put((String) test[0], (Integer) test[1]);
}
HashMap<String, Integer> map = sortHashMap(userGains);
for (int i = 0; i < map.size(); i++) {
System.out.println(testUsers[i][0] + " gained " + map.get(testUsers[i][0]) + " experience.");
}
}
public LinkedHashMap<String, Integer> sortHashMap(HashMap<String, Integer> passedMap) {
List<String> mapKeys = new ArrayList<String>(passedMap.keySet());
List<Integer> mapValues = new ArrayList<Integer>(passedMap.values());
LinkedHashMap<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
Collections.sort(mapValues);
Collections.sort(mapKeys);
Iterator<Integer> it$ = mapValues.iterator();
while (it$.hasNext()) {
Object val = it$.next();
Iterator<String> keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
String comp1 = passedMap.get(key).toString();
String comp2 = val.toString();
if (comp1.equals(comp2)) {
passedMap.remove(key);
mapKeys.remove(key);
sortedMap.put((String) key, (Integer) val);
break;
}
}
}
return sortedMap;
}
The output of the program is currently:
Test user gained 15 experience.
Test gained 25 experience.
Hello gained 11 experience.
I'm a user gained 21 experience.
No you're not! gained 14 experience.
Yes I am! gained 45 experience.
Oh, okay. Sorry about the confusion. gained 0 experience.
It's quite alright. gained 0 experience.
When I need it to be:
Yes I am! gained 45 experience. // start numeric sorting here, by highest key.
Test gained 25 experience.
I'm a user gained 21 experience.
Test user gained 15 experience.
No you're not! gained 14 experience.
Hello gained 11 experience.
It's quite alright. gained 0 experience. // start alphabetical sorting here, if possible.
Oh, okay. Sorry about the confusion. gained 0 experience.
Any insight?
It's not possible to sort a HashMap at all. By definition, the keys in a HashMap are unordered. If you want the keys of your Map to be ordered, then use a TreeMap with an appropriate Comparator object. You can create multiple TreeMaps with different Comparators if you want to access the same data multiple ways.
You made a mistake in displaying the values.
HashMap<String, Integer> map = sortHashMap(userGains);
for (int i = 0; i < map.size(); i++) {
System.out.println(testUsers[i][0] + " gained " + map.get(testUsers[i][0]) + " experience.");
}
You need to display the map's values instead of the original array's values.
This should do:
HashMap<String, Integer> map = sortHashMap(userGains);
for (Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " gained " + entry.getValue() + " experience.");
}
You only have to reverse the order. Further I recommend to declare against Map instead of HashMap or LinkedHashMap to avoid confusion by yourself and others. Also your sorting can simpler be done with a Comparable. Here's an improvement:
private Map<String, Integer> userGains = new HashMap<String, Integer>();
private Object[][] testUsers = { { "Test user", 15 }, { "Test", 25 }, { "Hello", 11 }, { "I'm a user", 21 }, { "No you're not!", 14 }, { "Yes I am!", 45 }, { "Oh, okay. Sorry about the confusion.", 0 }, { "It's quite alright.", 0 } };
public static void main(String[] arguments) {
new Sorting().sortGains();
}
public void sortGains() {
for (Object[] test : testUsers) {
userGains.put((String) test[0], (Integer) test[1]);
}
Map<String, Integer> map = createSortedMap(userGains);
for (Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " gained " + entry.getValue() + " experience.");
}
}
public Map<String, Integer> createSortedMap(Map<String, Integer> passedMap) {
List<Entry<String, Integer>> entryList = new ArrayList<Entry<String, Integer>>(passedMap.entrySet());
Collections.sort(entryList, new Comparator<Entry<String, Integer>>() {
#Override
public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2) {
if (!e1.getValue().equals(e2.getValue())) {
return e1.getValue().compareTo(e2.getValue()) * -1; // The * -1 reverses the order.
} else {
return e1.getKey().compareTo(e2.getKey());
}
}
});
Map<String, Integer> orderedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : entryList) {
orderedMap.put(entry.getKey(), entry.getValue());
}
return orderedMap;
}
This question approaches what you're trying to do, by sorting on value in a TreeMap. If you take the most voted answer and modify the Comparator to sort on value then key, it should give you what you want.
Effectively, you create a Comparator that has a field that points to the TreeMap (so it can look up values). And the TreeMap uses this Comparator. When items are added to the TreeMap, the Comparator looks up the values and does a comparison on
if the value a < value b, return 1
if the value a > value b, return -1
if the key a < key b, return 1
if the key a > key b, return -1
otherwise, return 0
Copying a lot of code from that answer (with no checking to see if the code works, since it's just for the idea):
public class Main {
public static void main(String[] args) {
ValueComparator<String> bvc = new ValueComparator<String>();
TreeMap<String,Integer> sorted_map = new TreeMap<String,Integer>(bvc);
bvc.setBase(sorted_map);
// add items
// ....
System.out.println("results");
for (String key : sorted_map.keySet()) {
System.out.println("key/value: " + key + "/"+sorted_map.get(key));
}
}
}
class ValueComparator implements Comparator<String> {
Map base;
public setBase(Map<String,Integer> base) {
this.base = base;
}
public int compare(String a, String b) {
Integer value_a = base.get(a);
Integer value_b = base.get(b);
if(value_a < value_b) {
return 1;
}
if(value_a>< value_b) {
return -1;
}
return a.compareTo(b);
}
}

Categories