Convert Map with Set of Strings as key to Map with Strings (Java)
Classes information below: Class Book Class Author I have also created a method to populate test data so I could test my other methods: What I need is a method which takes no argument, iterates through the map and prints out the combination map key + book info (book title and yearPublished So far, I have written the following: However, the output is rather strange: Any ideas on how I can get around on that? Solution 1: You need to override method of your class to get printable string.
Convert Map with Set of Strings as key to Map with Strings (Java)
the question is not difficult, and I have already solved it in my own way, but I would like to hear your opinion, maybe there is some way to make this an improved option? Java 8-11.
Imagine, that elements inside of the set are won’t repeat. One more note: many unique keys can point to the same value.
I made this with the following code:
Map result = new HashMap<>(); existingMap.forEach((set, user) -> set.forEach(item -> result.put(set, user)));
So, my question is — is there a better way to do it? I mean, maybe Stream API already has some methods to do it? in the scope of ‘collect’ method
If you want to use a collector, you can do a flatMap first, then toMap :
Map result = existingMap.entrySet().stream().flatMap( entry -> entry.getKey().stream() .map(s -> Map.entry(s, entry.getValue())) ) .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Or if you just want to use collect only (this is more similar to your original approach):
Map result = existingMap.entrySet().stream().collect( HashMap::new, (map, entry) -> entry.getKey().forEach(x -> map.put(x, entry.getValue())), HashMap::putAll );
This problem cannot be solved.
This is valid for structure 1 ( Map, User> ) but invalid for structure 2 ( Map ) as it will cause data loss (information about Bill and Tom will be lost).
An alternate structure you may consider is the conversion from Map, User> to Map> , which will not result in data degradation.
Edit: to assume data loss is acceptable as per the comments, a normal for loop solution would be:
Map results = new HashMap<>(); for (Set key : existing.keySet()) < User v = existing.get(key); for (String k : key) < results.put(k, v); >>
Accessing objects from a Set inside a Map in Java [duplicate]
I am trying to Create A Method In Java where when invoked it would go through the map, look for the key entered and retrieve the set of objects and its values from a collection.
For context, this is an application with two classes, Book and Author, where author holds a collection of books holding the attributes title and yearPublished. Classes information below:
public class Author < // instance variables private Map> bookSet; /** * Constructor for objects of class Author */ public Author() < bookSet = new HashMap<>(); >
I have also created a method to populate test data so I could test my other methods:
/** * This method can be used to populate test data. */ public void createTestData() < Setcollection = new HashSet<>(); Book book1 = new Book("Lord of the Flies",1954); Book book2 = new Book("Another Lord of the Flies",1955); Book book3 = new Book("Jamaica Inn",1936); collection.add(book1); collection.add(book2); collection.add(book3); bookSet.put("William Golding",collection); Set collection2 = new HashSet<>(); Book book4 = new Book("The Wind in the Willows",1908); Book book5 = new Book("Oliver Twist",1838); collection2.add(book4); collection2.add(book5); bookSet.put("Kenneth Grahame",collection2); >
What I need is a method which takes no argument, iterates through the map and prints out the combination map key + book info (book title and yearPublished
So far, I have written the following:
/** * Prints out to the standard output the authors currently in the system and all the books written * by them, together with the year it was published. */ public void printMap() < for (String key : bookSet.keySet()) < System.out.println(key + " " + bookSet.get(key)); >>
However, the output is rather strange:
William Golding [Book@e8a4d45, Book@4f196e15, Book@69f8d3cd] Kenneth Grahame [Book@19d6f478, Book@6f4bff88]
Any ideas on how I can get around on that?
Also, I am trying to come up with a method to retrieve the set of books, which takes one argument (the map key) and printing to the standard output the map key (author’s name) and all books written by them (title and yearPublished. This is what I have so far:
/** * Searches through the map for the key entered as argument. If the argument is a key in the map, prints * textual representation of its associated value, otherwise prints an output line announcing * that the key is not present. */ public void printMapValue(String aKey)
The results again are quite weird:
example.printMapValue("William Golding");
The books written by William Golding are: [Book@e8a4d45, Book@4f196e15, >Book@69f8d3cd]
I would really appreciate if someone could help me with that.
You need to override toString() method of your Book class to get printable string.
Every Java object implicitly extends/inherits from the Object class. When you print an object (say by passing it onto System.out.print) or concatenate it to a string (as in your case), it needs a string representation of your object. It gets this representation from toString method from the base( Object ) class. The default behavior of toString is
getClass().getName() + '@' + Integer.toHexString(hashCode())
Hence, you need to override it in your Book class to get a user friendly representation. One possible representation maybe,
@Override public String toString()
Simply override the toString() method of the Object class inside your Book class.
@Override public String toString() < return "Book'; >
How to Store Duplicate Keys in a Map in Java?, Obviously, using a Collection for every value of our Map would do the job: Map
Golang map put if absent?
I have a map of the format:
In this main map, I want to do something like putIfAbsent(«key», new HashMap<>() as we have in Java. What is a clean and shorthand way to do it in Go?
var val map[string]int val, exists := mJava convert set to map if !exists
If you don’t need the val in the code coming below this:
If you don’t intend to use the value right away, here you go.
m := make(map[string]map[string]int) if _, ok := m["unknown"]; !ok
Below is a suggestion for improvement: To keep things clean and easy to understand, you can define your own types. For example, if your data is a mapping of «cities to persons to age», I would do it like this:
type Person map[string]int type City map[string]Person m := make(City) if _, ok := m["Dhaka"]; !ok
func main() < var testMap map[int]interface<>testMap = make(map[int]interface<>) var addMap map[int]string addMap = make(map[int]string) addMap[1] = "999" addMap[2] = "888" Add(testMap, 111, addMap) for key, val := range testMap < fmt.Println(key) for key2, val2 := range val.(map[int]string) < fmt.Println(key2, val2) >> >
func Add(_testMap map[int]interface<>, _key int, _val map[int]string) < _, exist := _testMap[_key] // _ ->value if exist == false < //addmap _testMap[_key] = _val >else < //whatever wanna to do >>
Optimized implementations of java.util.Map and java.util.Set?, Normally these methods are pretty quick. There are a couple of things you should check: are your hash codes implemented? Are they sufficiently uniform?
Converting Collections to Maps With JDK 8
Join the DZone community and get the full member experience.
I have run into situations several times where it is desirable to store multiple objects in a Map instead of a Set or List because there are some advantages from using a Map of unique identifying information to the objects. Java 8 has made this translation easier than ever with streams and the Collectors.toMap(. ) methods.
One situation in which it has been useful to use a Map instead of a Set is when working with objects that lack or have sketchy equals(Object) or hashCode() implementations, but do have a field that uniquely identifies the objects. In those cases, if I cannot add or fix the objects’ underlying implementations, I can gain better uniqueness guarantees by using a Map of the uniquely identifying field of the class (key) to the class’s instantiated object (value). Perhaps a more frequent scenario when I prefer Map to List or Set is when I need to lookup items in the collection by a specific uniquely identifying field. A map lookup on a uniquely identifying key is speedy and often much faster than depending on iteration and comparing each object with an invocation to the equals(Object) method.
With JDK 8, it’s easier than ever to construct a Map from an existing List or Set . To help demonstrate this, a simple Book class will be used. This Book class does not override equals(Object) or hashCode() from the Object class and so is not an appropriate class to use in a Set or as a Map key. However, its getIsbn() method returns an International Standard Book Number that is assumed unique for purposes of this demonstration.
package dustin.examples.jdk8; /** * Represents a book, but does not override * or . */ public class Book < /** International Standard Book Number (ISBN-13). */ final String isbn; /** Title of book. */ final String title; /** Edition of book. */ final int edition; /** * Constructor. * * @param newIsbn International Standard Book Number (-13). * @param newTitle Title. * @param newEdition Edition. */ public Book(final String newIsbn, final String newTitle, final int newEdition) < isbn = newIsbn; title = newTitle; edition = newEdition; >/** * Provide ISBN-13 identifier associated with this book. * * @return ISBN-13 identifier. */ public String getIsbn() < return isbn; >/** * Provide title of this book. * * @return Book's title. */ public String getTitle() < return title; >/** * Provide edition of this book. * * @return Book's edition. */ public int getEdition() < return edition; >@Override public String toString() < return title + " (Edition " + edition + ") - ISBN-13: " + isbn; >>
With this class in place, the demonstration class CollectionToMapDemo shows how easy it is with JDK 8 to convert various Java collection types ( Set , List , and even arrays) to a Map .
CollectionToMapDemo.java:
package dustin.examples.jdk8; import static java.lang.System.out; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * Demonstrates conversion of Java collections to Java Maps. */ public class CollectionToMapDemo < /** * Multiple instances of Book, a class that lacks a proper * equals(Object) method, but for which its getIsbn() method * is assumed to return a unique identifier for each instance. */ private static final Book[] books; static < books = new Book[] < new Book("978-0-201-31005-4", "Effective Java", 1), new Book("978-0-321-35668-0", "Effective Java", 2), new Book("978-0-13-468599-1", "Effective Java", 3) >; > /** * Convert provided array of Book instances to Map of each Book's ISBN to * that instance of the Book. * * @param booksArray Array of Book instances. * @return Map of each book's ISBN (key) to the book's full instance (value). */ private static Map < String, Book >convertArrayToMap(final Book[] booksArray) < return Arrays.stream(booksArray).collect( Collectors.toMap(Book::getIsbn, book - >book)); > /** * Convert provided List of Book instances to Map of each Book's ISBN to * that instance of the Book. * * @param booksList List of Book instances. * @return Map of each book's ISBN (key) to the book's full instance (value). */ private static Map < String, Book >convertListToMap(final List < Book >booksList) < return booksList.stream().collect( Collectors.toMap(Book::getIsbn, book - >book)); > /** * Convert provided Set of Book instances to Map of each Book's ISBN to * that instance of the Book. * * @param booksSet Set of Book instances. * @return Map of each book's ISBN (key) to the book's full instance (value). */ private static Map < String, Book >convertSetToMap(final Set < Book >booksSet) < return booksSet.stream().collect( Collectors.toMap(Book::getIsbn, book - >book)); > public static void main(final String[] arguments) < out.println("ARRAY->MAP:\n" + convertArrayToMap(books)); final List < Book >booksList = Arrays.asList(books); out.println("LIST->MAP:\n" + convertListToMap(booksList)); final Set < Book >booksSet = new HashSet < >(Arrays.stream(books).collect(Collectors.toSet())); out.println("SET->MAP:\n" + convertSetToMap(booksSet)); > >
The most important methods in the class listing just shown are convertArrayToMap(Book[]) , convertListToMap(List) , and convertSetToMap(Set) . All three implementations are the same once a stream based on the underlying Set , List , or array has been accessed. In all three cases, it’s merely a matter of using one of the stream’s collect() method (a reduction operator that is typically preferable over sequential iteration) and passing it an implementation of the Collector interface that is provided via a predefined toMap() Collector from the Collectors class.
The output from running this demonstration class against the instances of Book is shown next:
I have run into several situations in which it has been advantageous to have multiple objects in a Map of unique identifier to full instance of those objects, but have been given the objects in a Set , List , or array. Although it’s never been particularly difficult to convert these Set s, List s, and arrays to Map s in Java, it’s easier than ever in Java 8 to make this conversion.
Published at DZone with permission of Dustin Marx , DZone MVB . See the original article here.
Opinions expressed by DZone contributors are their own.