Quick question and its probably the most simple answer but i need to print a textual representation of my HashMaps contents.
My code so far is:
public void printAll() {
Set< String> Names = customersDetails.keySet();
Collection< CustomerDetails> eachCustomersNames = customersDetails.values();
for (String eachName : Names) {
System.out.println(eachName)
}
for (CustomerDetails eachCustomer : eachCustomersNames) {
System.out.println(eachCustomer);
}
}
But this results in the list of keys and then a list of values but i need each line of text to read something like
Bob [example]
Where Bob is the key and example is the value.
If you're using Java 8, you can take advantage of lambda syntax and .forEach() like so:
customersDetails.forEach((k,v) -> {
System.out.println(k + "[" + v + "]");
});
Where k is your key and v is the value tied to key k.
Every key maps to just one value, so you can just do this:
Set < String> Names = customersDetails.keySet();
for (String eachName: Names) {
System.out.println(eachName + " [" + customersDetails.get(eachName).toString() + "]")
}
If you're not using Java 8, simply print both key and value for each key:
for (String eachName : Names) {
System.out.println(eachName + " [" + customersDetails.get(eachName) + "]");
}
You can print your Map like so :
Map<String, String> customersDetails = new HashMap<>();
for (Map.Entry<String, String> entry : customersDetails.entrySet()) {
System.out.println(entry.getKey() + '[' + entry.getValue() + ']');
}
If you are using java 8 you can use :
customersDetails.entrySet().forEach((entry) -> {
System.out.println(entry.getKey() + '[' + entry.getValue() + ']');
});
If you start dealing with maps with more complicated types consider using ReflectionToStringBuilder. Internally it uses reflection to build a string of an object and its fieldd. It recurses through the object graph too.
It may not be efficient, but it helps a lot with debugging and printing operations.
You don't need to iterate over your keys/values in order to print your map, as the HashMap.toString() method already does this for you very efficiently (actually, it's the AbstractMap.toString() method).
If you have your CustomerDetails class implement the toString() method, then you only need to do:
System.out.println(customerDetails);
And this will print your map in the format you require.
Related
I have an object of Optional<Map<String,Map<String,String[]>>> How do I loop over each string in the array?
The below code I am expecting "application" to be 'String' but it gives me 'String[]'
Optional<Map<String,Map<String,String[]>>> myObject = Optional.of(yamlReader.read(name, HashMap.class));
Set<Map.Entry<String, Map<String, String[]>>> abc = myObject.get().entrySet();
for ( Map.Entry<String, Map<String, String[]>> x:abc) {
Map<String, String[]> v = x.getValue();
//I am expecting "application" to be String here but it is an array of Strings for some reason
for (String[] application: v.values()) {
System.out.println(application + " " + x.getKey());
}
You need to iterate through the String[] to get individual values.
May be you might need to verify the given requirement with structure you are using now.
for (Map.Entry<String, Map<String, String[]>> x : abc) {
Map<String, String[]> v = x.getValue();
v.values().forEach(value -> {
System.out.println("value:" + " " + value);
});
}
it is an array of String because v.values() is Collection<String[]>, it is not just String. if you want to print only String, you would need to flat that out.
So if you end goal is to just print all Strings available in your collection, you can use below code.
myObject.ifPresent(map -> map.values().stream().map(Map::values).flatMap(Collection::stream).flatMap(Arrays::stream).forEach(System.out::println));
or if you would like to tweak your code, do something like below to replace your for last loop
v.values().stream().flatMap(Arrays::stream).forEach(application -> System.out.println(application + " " + x.getKey()));
OR
for (String[] application: v.values()) {
System.out.println(Arrays.asList(application) + " " + x.getKey());
}
This question already has answers here:
Multi-line pretty-printing of (nested) collections in Java
(4 answers)
Closed 6 years ago.
I want to print a nested HashMap which is :
HashMap<Integer,HashMap<Character,Integer>> map;
I searched a lot but I can't find a way to print the Integer because when I use getValues() on it, it tells me : "cannot find symbol". (Because it's an Integer value)
This is what I tried to do :
public void print(){
for(Map.Entry<Integer, HashMap<Character,Integer>> t :this.map.entrySet()){
Integer key = t.getKey();
for (Map.Entry<Character,Integer> e : this.map.getValue().entrySet())
System.out.println("OuterKey:" + key + " InnerKey: " + e.getKey()+ " VALUE:" +e.getValue());
}
}
I can't use getValue() in my second for, so what else can I use ?
Thanks in advance !
Have a nice day.
Chris.
getValue() is a method of Map.Entry, not Map.
You should use t.getValue().entrySet() instead of this.map.getValue().entrySet() in the second loop.
That would give you the inner Map.
public void print(){
for(Map.Entry<Integer, HashMap<Character,Integer>> t :this.map.entrySet()){
Integer key = t.getKey();
for (Map.Entry<Character,Integer> e : t.getValue().entrySet())
System.out.println("OuterKey:" + key + " InnerKey: " + e.getKey()+ " VALUE:" +e.getValue());
}
}
The easiest way to print the whole thing:
System.out.println(map.toString());
Yep, thats it; toString() returns a string ... that contains all the content of your Map; including its inner Map!
If you want to do that yourself, then you can use two loops:
for(Map.Entry<Integer, HashMap<Character,Integer>> innerMap : map.entrySet()) {
for (Map.Entry<Character, Integer> aMap : innerMap.entrySet) {
... now you can call aMap.getKey() and .getValue()
public static void main(String[] args) {
HashMap<Integer,HashMap<Character,Integer>> map = new HashMap<Integer,HashMap<Character,Integer>>();
HashMap<Character,Integer> map1 = new HashMap<Character,Integer>();
map1.put('1', 11);
HashMap<Character,Integer> map2 = new HashMap<Character,Integer>();
map2.put('2', 22);
map.put(111, map1);
map.put(222, map2);
for (Integer temp : map.keySet()) {
for (Character c : map.get(temp).keySet()) {
System.out.println("key--" + c + "--value--" + map.get(temp).get(c));
}
}
}
Hope it works.
How do I scroll a LinkedHashMap to a specific key? Something like this:
LinkedHashMap<String,String> queque = new LinkedHashMap<String,String>();
queque.put("uno","uno");
queque.put("due","due");
queque.put("tre","tre");
queque.put("quattro","quattro");
queque.put("cinque","cinque");
Iterator i = queque.entrySet().iterator();
while(i.next().getKey().equals(quattro)) {
System.out.print(i.getKey() + ": ");
System.out.println(i.getValue());
i.next();
}
You don't have to explicitly iterate (unless you really want to) to get the value by key: just use get() method:
System.out.println("quattro" + ": " + queque.get("quattro"));
If you want to print all the values up to the certain one, you can do the following:
Iterator i = queque.entrySet().iterator();
while(i.hasNext()) {
Map.Entry<String, String> me = i.next();
if (me.getKey() == "quattro") break;
System.out.println(me.getKey() + ": " + me.getValue());
}
Or, a little more elegant:
for (Map.Entry<String, String> me : queque.entrySet()) {
if (me.getKey() == "quattro") break;
System.out.println(me.getKey() + ": " + me.getValue());
}
Couple more points:
If you do not need to store the elements in the order they were added, use HashMap rather than LinkedHashMap, since former is faster. If you want store elements sorted, use TreeMap(but beware it is slower than the other types of Map).
When you create instance of container in Java, you are better off using interface (like Map, List or Set) in the left part of assignment and implementation (like HashMap, ArrayList etc.) in the right part since it gives you much more flexibility: in case you later on decide to change the implementation of the same interface (e.g. use HashMap instead of LinkedHashMap as I suggested above), you only need to change one line of your code where you create this container, rather than change all places where this container is used.
If you want to do it right with Iterator you would do
Iterator<Entry<String, String>> i = queque.entrySet().iterator();
while (i.hasNext()) {
Entry<String, String> entry = i.next();
if ("quattro".equals(entry.getKey()))
break;
System.out.println(entry.getKey() + ": " + entry.getValue());
}
But that is equivalent to using an enhanced for loop like so:
for (Entry<String, String> entry : queque.entrySet()) {
if ("quattro".equals(entry.getKey()))
break;
System.out.println(entry.getKey() + ": " + entry.getValue());
}
with Iterator you'll have to check hasNext(), only then call next() once(!) per loop or your iterator would advance by two elements. You should also never compare Strings with ==, that's just not working.
Sounds like you should be using TreeMap to me. Then you just use TreeMap.headMap().
First time here so I hope this makes sense!
I have a Map which contains a String as it's Key, and a List of Strings as it's Value. I need to iterate over all vlaues contained within each List within the Map.
So, first I want to get the Keys, which works:
Set<String> keys = theMap.keySet();
This returns me a Set containing all my Keys. Great :)
This is where I've got stuck - most of the info on the web seems to assume that the values I'd want returned from the Key would be a simple String or Integer, not another Set, or in this case a List. I tried theMap.values() but that didn't work, and I tried a forloop / for:eachloop, and neither of those did the trick.
Thanks y'all!
for(List<String> valueList : map.values()) {
for(String value : valueList) {
...
}
}
That's really the "normal" way to do it. Or, if you need the key as well...
for(Map.Entry<String, List<String>> entry : map.entrySet()) {
String key = entry.getKey();
for (String value : entry.getValue()) {
...
}
}
That said, if you have the option, you might be interested in Guava's ListMultimap, which is a lot like a Map<K, List<V>>, but has a lot more features -- including a Collection<V> values() that acts exactly like what you're asking for, "flattening" all the values in the multimap into one collection. (Disclosure: I contribute to Guava.)
I recommend iterating over Map.entrySet() as it is faster (you have both, the key and the value, found in one step).
Map<String, List<String>> m = Collections.singletonMap(
"list1", Arrays.asList("s1", "s2", "s3"));
for (Map.Entry<String, List<String>> me : m.entrySet()) {
String key = me.getKey();
List<String> valueList = me.getValue();
System.out.println("Key: " + key);
System.out.print("Values: ");
for (String s : valueList) {
System.out.print(s + " ");
}
}
Or the same using the Java 8 API (Lambda functions):
m.entrySet().forEach(me -> {
System.out.println("Key: " + me.getKey());
System.out.print("Values: ");
me.getValue().forEach(s -> System.out.print(s + " "));
});
Or with a little bit of Java Stream API mapping hardcore and method reference :-)
m.entrySet().stream().map(me -> {
return "Key: " + me.getKey() + "\n"
+ "Values: " + me.getValue().stream()
.collect(Collectors.joining(" "));
})
.forEach(System.out::print);
And the output is, as expected:
Key: list1
Values: s1 s2 s3
You need a Map<String, List<String>>
The left hand side String is the key, the right hand side List<String> is the value, which in this case is a List of Strings
Another example with the Java 8 API (lambda function).
When you want to iterate over:
Map<String, List<String>> theMap = new HashMap<>();
theMap.forEach((key, value) -> {
System.out.println("KEY: " + key);
System.out.print("VALUES: ");
value.forEach(System.out::println);
});
I am trying to compile the following code:
private String dataToString(){
Map data = (HashMap<MyClass.Key, String>) getData();
String toString = "";
for( MyClass.Key key: data.keySet() ){
toString += key.toString() + ": " + data.get( key );
return toString;
}
I get an error in the for line that says:
incompatible types
found : java.lang.Object
required: MyClass.Key
The getData() method returns an Object (but in this case the Object returned has the HashMap structure). MyClass.Key is an enum that I have created for the purposes of my application (in another class file - MyClass).
When I created a foreach loop with the same structure in MyClass.java, I did not encounter this problem.
What am I doing wrong?
A slightly more efficient way to do this:
Map<MyClass.Key, String> data = (HashMap<MyClass.Key, String>) getData();
StringBuffer sb = new StringBuffer();
for (Map.Entry<MyClass.Key,String> entry : data.entrySet()) {
sb.append(entry.getKey());
sb.append(": ");
sb.append(entry.getValue());
}
return sb.toString();
If at all possible, define "getData" so you don't need the cast.
Change:
Map data = (HashMap<MyClass.Key, String>) getData();
to
Map<MyClass.Key, String> data = (HashMap<MyClass.Key, String>) getData();
The problem is that data.keySet() returns a Collection<Object> if data is just a Map. Once you make it generic, keySet() will return a Collection<MyClass.Key>. Even better... iterate over the entrySet(), which will be a Collection<MyClass.Key, String>. It avoids the extra hash lookups.
You could grab the entrySet instead, to avoid needing the key class:
private String dataToString(){
Map data = (HashMap<MyClass.Key, String>) getData();
String toString = "";
for( Map.Entry entry: data.entrySet() ) {
toString += entry.getKey() + ": " + entry.getValue();
}
return toString;
}
I found this simple example at java forum. Its syntax is very similar to the List's foreach, which was what I was looking for.
import java.util.Map.Entry;
HashMap nameAndAges = new HashMap<String, Integer>();
for (Entry<String, Integer> entry : nameAndAges.entrySet()) {
System.out.println("Name : " + entry.getKey() + " age " + entry.getValue());
}
[EDIT:] I tested it and it works perfectly.
Motlin's answer is correct.
I have two notes...
Don't use toString += ..., but use StringBuilder instead and append data to it.
Cast which Martin suggested will give you unchecked warning, which you won't be able to get rid of, because it is really unsafe.
Another way, without warning (and with StringBuilder):
private String dataToString(){
Map<?, ?> data = (Map<?, ?>) getData();
StringBuilder toString = new StringBuilder();
for (Object key: data.keySet()) {
toString.append(key.toString());
toString.append(": ");
toString.append(data.get(key));
}
return toString.toString();
}
This works, because toString method which you call on key is defined in Object class, so you don't need casting at all.
Using entrySet is even better way, as it doesn't need to do another look-up in map.