Is a HashMap a proper data structure - java

I store in a HashMap 3 types of object.
HashMap<String, ArrayList<Car>>
['Lorry', [list of lorries]]
['Sport', [list of sport's cars]]
The HashMap string key keeps the type of object (a subclass of Car), the second element stores in array the objects that have e.g. attributes like: ID, date etc.
The four main things I have to do are:
Check if certain ID exist in HashMap when there is no information provided about its type
Print elements of certain ID given the type.
Print all elements of certain type
Print all element from the collection (of different types) if certain attribute that each object has assigned has a Boolean value of e.g. "true";
Is the HashMap the proper structure? I find it problematic if it comes to the first point. It seems like I will have to traverse the whole collection and if so what other collection is better for such requirements?

The basic approach is sound, however since you only want to store each instance once, a Set is a better choice than a List for the map entry value:
Map<String, Set<Car>> typeCache = new HashMap<String, HashSet<Car>>();
The contains() method of HashSet is very fast indeed, so finding if your map contains a particular instance in it values is not going to cost much.
Using two maps would probably be better though - once for each type of lookup, so also use:
Map<String, Object> idCache = new HashMap<String, Object>();

A HashMap is the right data structure for the job, but in your case you might consider using two HashMaps: One holding the relation 'Car Type' -> 'Cars of that Type', and a second one for the relation 'ID' -> 'Car with that ID'.

Related

How to conditionally insert a Map into a list in Java if the list does not already include a map containing a key value pair

I have a list of HashMap objects in Java.
I would like to conditionally add more HashMap objects to this list if the list does not already contain a HashMap having the same key value pair as in the new HashMap.
Here is an example HashMap list. Note that in reality, there are more keys. Here, I am just including "contact_id" for simplicity.
[{contact_id=16247115}, {contact_id=16247116}, {contact_id=16247117}, {contact_id=16247118}, {contact_id=16247119}]
Adding {contact_id=16247117} to this list should not be allowed.
Adding {contact_id = 74857983}, should be allowed.
Ideally, I would like to be able to conditionally add several HashMaps into this list in one line of code. If I were not to perform the conditional check, I could just use the syntax listname.addAll(batchOfHashMaps). I'd like to do something similar, but precluding redundant HashMaps in the list.
What is the most efficient way to achieve this conditional insert in Java?
I reckon there must be a more efficient solution than evaluating each element in the list inside a for-loop.
If you are only wanting to look at one key-value pair of the maps as an identifier, then you could use a Map instead of a List to hold everything. For example,
Map<String, Map<String, String> mapOfMaps;
Then you could add one like:
mapOfMaps.putIfAbsent(mapToAdd.get("contact_id"), mapToAdd);
you could add multiple like:
batchOfHashMaps.forEach(m -> mapOfMaps.putIfAbsent(m.get("contact_id"), m));
To get a collection of your maps simply call values()
mapOfMaps.values();

Re-order Map based on ordering of List

Lets say I have two data structures, an ordered List of Strings and a HashMap. The List looks like:
types = ["string", "integer", "boolean", "integer"];
And the HashMap, with an object key and a String value, that looks like:
map = {2=integer, true=boolean, 7=integer, "dog"=string};
Whats the easiest/most efficient way to reorganize the "order" of the Map so that the Map's values align with the ordering of the list, i.e., the Map would now look like this when printed:
map = {"dog"=string, 2=integer, true=boolean, 7=integer};
HashMap does not offer an order guarantee. From the documentation:
This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
So if you wanted an ordered Map you'd normally want to start with an implementation of SortedMap (documentation).
Unfortunately, SortedMap sorts by key, and you want to sort by value, so you're either going to have to look at third-party collection libraries or consider something like LinkedHashMap (documentation), which has a predictable iteration order, even if it doesn't maintain a sort.
What strategy would you be using to decide which integer to use when there's two as your example shows?
Build a reverse hashmap like so,
types = ["string", "integer", "boolean", "integer"];
map = {2=integer, true=boolean, 7=integer, "dog"=string};
reversedmap = {integer=[2,7], boolean=true, string=dog};
then iterate through the list and the get the corresponding keys from the reversedmap.
for example, first you get "string" from types -> so you know the corresponding key should be "dog". Insert this key-value pair in some other map (of type LinkedHashMap). Keep on doing this till you reach the end of types list.
EDIT: Thank you #FedericoPeraltaSchaffner for pointing this out.
If you get two values from the reversedmap (for eg, in case of "integer" element), you can choose one of them (doesn't matter which) to be inserted in the LinkedHashMap while also subsequently removing it from the reversedmap. And then you procced to the next element in the types list

Comparing an ArrayList of Integer to more than one ArrayList to extract common values

I have one ArrayList of Integer, extracted from a MapDB map, with this code:
ArrayList<Integer> idOffUser=users.get(myUser).getOffers();
It's a list of ids.
I have another ConcurrentNavigableMap from the same db, called auctions. In this map for every object which mantains I have an ArrayList of Integer, called offId, which has a list of unique integers, each one representing a specific offer. Every offId it's reffered to a specific object (an auction) of that map.
In every offId there can be (or not!) a match for some elements of idOffUser, so I need to extract the objects in auctions whose offId has at least a match with an element of idOffUser, excluding the duplicates, because I only need to know in what auction an user put an offer, but an user can put multiple offers in an auction.
As a result of this method I need to have an ArrayList with every auction object in which an user put at least an offer.
So far, I know I can access an arraylist of offers in auctions in this way:
for (Auction key : auctions.values())
key.getOffId();
Something like this shoul do the trick:
Set<Integer> uniqueIds = new HashSet<>();
for (Auction key : auctions.values())
uniqueIds.addAll(key.getOffId());
List<Integer> idsOfUsersWithAuctions = idOffUser.stream().filter(id -> uniqueIds.contains(id)).collect(Collectors.toList());

When to use a Map instead of a List in Java?

I didn't get the sense of Maps in Java. When is it recommended to use a Map instead of a List?
Say you have a bunch of students with names and student IDs. If you put them in a List, the only way to find the student with student_id = 300 is to look at each element of the list, one at a time, until you find the right student.
With a Map, you associate each student's ID and the student instance. Now you can say, "get me student 300" and get that student back instantly.
Use a Map when you need to pick specific members from a collection. Use a List when it makes no sense to do so.
Say you had exactly the same student instances but your task was to produce a report of all students' names. You'd put them in a List since there would be no need to pick and choose individual students and thus no need for a Map.
Java map: An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
Java list: An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.
The difference is that they are different. Map is a mapping of key/values, a list of a list of items.
I thinks its a lot the question of how you want to access your data. With a map you can "directly" access your items with a known key, in a list you would have to search for it, evan if its sorted.
Compare:
List<MyObject> list = new ArrayList<MyObject>();
//Fill up the list
// Want to get object "peter"
for( MyObject m : list ) {
if( "peter".equals( m.getName() ) {
// found it
}
}
In a map you can just type
Map<String, MyObject> map = new HashMap<String, MyObject>();
// Fill map
MyObject getIt = map.get("peter");
If you have data to process and need to do it with all objects anyway, a list is what you want. If you want to process single objects with well known key, a map is better.
Its not the full answer (just my 2...) but I hope it might help you.
A map is used as an association of a key and a value. With a list you have basically only values.
The indexes in List are always int, whereas in Map you can have another Object as a key.
Resources :
sun.com - Introduction to the Collections Framework, Map
Depends on your performance concerns. A Map more explicitly a HashMap will guarantee O(1) on inserts and removes. A List has at worst O(n) to find an item. So if you would be so kind as to elaborate on what your scenario is we may help more.
Its probably a good idea to revise Random Access Vs Sequential Access Data Structures. They both have different run time complexities and suitable for different type of contexts.
When you want to map instead of list. The names of those interfaces have meaning, and you shouldn't ignore it.
Use a map when you want your data structure to represent a mapping for keys to values. Use a list when you want your data to be stored in an arbitrary, ordered format.
Map and List serve different purpose.
List holds collection of items. Ordered (you can get item by index).
Map holds mapping key -> value. E.g. map person to position: "JBeg" -> "programmer". And it is unordered. You can get value by key, but not by index.
Maps store data objects with unique keys,therefore provides fast access to stored objects. You may use ConcurrentHashMap in order to achieve concurrency in multi-threaded environments.
Whereas lists may store duplicate data and you have to iterate over the data elements in order to access a particular element, therefore provide slow access to stored objects.
You may choose any data structure depending upon your requirement.

Difference between HashMap and ArrayList in Java?

In Java, ArrayList and HashMap are used as collections. But I couldn't understand in which situations we should use ArrayList and which times to use HashMap. What is the major difference between both of them?
You are asking specifically about ArrayList and HashMap, but I think to fully understand what is going on you have to understand the Collections framework. So an ArrayList implements the List interface and a HashMap implements the Map interface. So the real question is when do you want to use a List and when do you want to use a Map. This is where the Java API documentation helps a lot.
List:
An ordered collection (also known as a
sequence). The user of this interface
has precise control over where in the
list each element is inserted. The
user can access elements by their
integer index (position in the list),
and search for elements in the list.
Map:
An object that maps keys to values. A
map cannot contain duplicate keys;
each key can map to at most one value.
So as other answers have discussed, the list interface (ArrayList) is an ordered collection of objects that you access using an index, much like an array (well in the case of ArrayList, as the name suggests, it is just an array in the background, but a lot of the details of dealing with the array are handled for you). You would use an ArrayList when you want to keep things in sorted order (the order they are added, or indeed the position within the list that you specify when you add the object).
A Map on the other hand takes one object and uses that as a key (index) to another object (the value). So lets say you have objects which have unique IDs, and you know you are going to want to access these objects by ID at some point, the Map will make this very easy on you (and quicker/more efficient). The HashMap implementation uses the hash value of the key object to locate where it is stored, so there is no guarentee of the order of the values anymore. There are however other classes in the Java API that can provide this, e.g. LinkedHashMap, which as well as using a hash table to store the key/value pairs, also maintains a List (LinkedList) of the keys in the order they were added, so you can always access the items again in the order they were added (if needed).
If you use an ArrayList, you have to access the elements with an index (int type). With a HashMap, you can access them by an index of another type (for example, a String)
HashMap<String, Book> books = new HashMap<String, Book>();
// String is the type of the index (the key)
// and Book is the type of the elements (the values)
// Like with an arraylist: ArrayList<Book> books = ...;
// Now you have to store the elements with a string key:
books.put("Harry Potter III", new Book("JK Rownling", 456, "Harry Potter"));
// Now you can access the elements by using a String index
Book book = books.get("Harry Potter III");
This is impossible (or much more difficult) with an ArrayList. The only good way to access elements in an ArrayList is by getting the elements by their index-number.
So, this means that with a HashMap you can use every type of key you want.
Another helpful example is in a game: you have a set of images, and you want to flip them. So, you write a image-flip method, and then store the flipped results:
HashMap<BufferedImage, BufferedImage> flipped = new HashMap<BufferedImage, BufferedImage>();
BufferedImage player = ...; // On this image the player walks to the left.
BufferedImage flippedPlayer = flip(player); // On this image the player walks to the right.
flipped.put(player, flippedPlayer);
// Now you can access the flipped instance by doing this:
flipped.get(player);
You flipped player once, and then store it. You can access a BufferedImage with a BufferedImage as key-type for the HashMap.
I hope you understand my second example.
Not really a Java specific question. It seems you need a "primer" on data structures. Try googling "What data structure should you use"
Try this link http://www.devx.com/tips/Tip/14639
From the link :
Following are some tips for matching the most commonly used data structures with particular needs.
When to use a Hashtable?
A hashtable, or similar data structures, are good candidates if the stored data is to be accessed in the form of key-value pairs. For instance, if you were fetching the name of an employee, the result can be returned in the form of a hashtable as a (name, value) pair. However, if you were to return names of multiple employees, returning a hashtable directly would not be a good idea. Remember that the keys have to be unique or your previous value(s) will get overwritten.
When to use a List or Vector?
This is a good option when you desire sequential or even random access. Also, if data size is unknown initially, and/or is going to grow dynamically, it would be appropriate to use a List or Vector. For instance, to store the results of a JDBC ResultSet, you can use the java.util.LinkedList. Whereas, if you are looking for a resizable array, use the java.util.ArrayList class.
When to use Arrays?
Never underestimate arrays. Most of the time, when we have to use a list of objects, we tend to think about using vectors or lists. However, if the size of collection is already known and is not going to change, an array can be considered as the potential data structure. It's faster to access elements of an array than a vector or a list. That's obvious, because all you need is an index. There's no overhead of an additional get method call.
4.Combinations
Sometimes, it may be best to use a combination of the above approaches. For example, you could use a list of hashtables to suit a particular need.
Set Classes
And from JDK 1.2 onwards, you also have set classes like java.util.TreeSet, which is useful for sorted sets that do not have duplicates. One of the best things about these classes is they all abide by certain interface so that you don't really have to worry about the specifics. For e.g., take a look at the following code.
// ...
List list = new ArrayList();
list.add(
Use a list for an ordered collection of just values. For example, you might have a list of files to process.
Use a map for a (usually unordered) mapping from key to value. For example, you might have a map from a user ID to the details of that user, so you can efficiently find the details given just the ID. (You could implement the Map interface by just storing a list of keys and a list of values, but generally there'll be a more efficient implementation - HashMap uses a hash table internally to get amortised O(1) key lookup, for example.)
A Map vs a List.
In a Map, you have key/value pairs. To access a value you need to know the key. There is a relationship that exists between the key and the value that persists and is not arbitrary. They are related somehow. Example: A persons DNA is unique (the key) and a persons name (the value) or a persons SSN (the key) and a persons name (the value) there is a strong relationship.
In a List, all you have are values (a persons name), and to access it you need to know its position in the list (index) to access it. But there is no permanent relationship between the position of the value in the list and its index, it is arbitrary.

Categories