Most suitable Java Collection for duplicate elements - java

I'm currently working on one project. I am trying to create a management system for a store. The problem is I need some sort of collection for stock, where while adding elements that already exist with the same name (updating the number of same item) it's state (attribute stockLevel) would update accordingly to the given quantity. Does anyone know which should be the best to let do such a thing? Map, Set or List?

That would a multiset (a.k.a. a bag). You can easily roll your own implementation as a Map<Item, Integer>, or use one of the existing classes, e.g. Google Guava's Multiset. Apache Commons Collections also have one, so do Eclipse Collections etc.

where while adding elements that already exist with the same name
(updating the number of same item) it's state (attribute stockLevel)
would update accordingly to the given quantity
In your usecase, Map is good to store the information :
Map<Product, StockLevel> for representing a map with as key Product and as value the number of it in stocks : StockLevel
For iterating on a Map, you could not keep the insertion order with a HashMap but for your need, it should not be a problem.
Nevertheless, if you want to keep the insertion order when you iterate on it or that you want that the map be ordered according to some needs (alphabetical or other), you can use more sophisticated map such as TreeMap or LinkedHashMap

Set do not allow duplicate values, but this is not a solution. If you insert a duplicate value it will be ignored. You can choose a List of Items and then loop to find duplicates. An if condition can be added to increment it's state.

Related

hash map, hash set, tree map, tree set - which to choose

I am trying to justify whether I'm using the most appropriate Data Structure for a set of scenarios.
The first scenario is an estate agent selling properties at different prices where no price is duplicated. Customers choose a range of prices & obtain a list of properties in that range.
To store the collection of property data I would choose TreeSet. As no property will have the same price, I could have pairs of: price (key) and value (property details). This would work with a TreeSet because there are no duplicate entries and the TreeSet could sort price in natural order. Additionally, the main operation for the scenario is search/contains which would take O(log n). Although there are faster search/contain operations e.g. HashMap, I need ordering. If I need to insert or delete an entry, I believe these operations are also O(log n).
To return a list of properties within a price range, I think I can use headSet() method?
However, I've read on some threads that I can store as a HashMap and create a TreeSet from the HashMap; would it be worth doing this?
You need an ordered set to be able to serve this type of queries. Therefor a tree structure is better suited for your needs than a hash map. However the equivalent to a HashMap is TreeMap, not a TreeSet - you need a mapping between key and value. As for the range operations there is a method more suited for your needs - subMap.

Multi key, linked hash

I have a set of elements with two properties, a name (string, not unique) and id (integer, unique). All elements with the same name are stored together, sorted according to some criteria.
Insertion is done just once as all elements are known beforehand, so it can be done easily. Deletion is done according to either the order (the first one) or eventually the id. Reading the values will be the most common (and relevant) operation.
Performance is the top requirement for the data-structure. I thought a multikey, linked data structure or a mixed hashmap/stack would be ideal, but I know non. Some options I considered are:
- Guava tables (multiple keys), but they don't have push/pop behaviors.
- LinkedHashMaps, but they just have one key.
Of course I can use LinkedHasMaps and iterate for deletion for those cases in which I have to delete an element based on the id. I just want to know if there is something out there already implemented with high performance.
Any suggestions?
Thanks to everyone
Use a Map<String, TreeSet<Integer>>. This will allow you to store several items under the same key, and keep the integer values sorted.
The idea is that you have a single key map to a data structure that can hold multiple values. To insert a name, value pair, you could do something like:
private Map<String, TreeSet<Integer>> map = new HashMap<>();
public void insert(String name, int value)
{
if (! map.containsKey(name))
{
map.put(name, new TreeSet<Integer>());
}
map.get(name).add(value);
}
A LinkedHashMap just keeps track of insertion order of the keys, and iterates in that order--it wouldn't improve performance over using a HashMap.

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.

Maintaining order of items in java

What is the best way to do the following(make sure that items from List are following the same order as those in ListTwo):
List
harry~20
marry~22
peter~40
jerry~33
janice~20
ListTwo
harry
marry
peter
janice
Now the result should look like this
ListThree
harry
marry
peter
janice
jerry
Step by step :
For each item in List :
compare first part of the item to item in ListTwo
if they are equal add it to ListThree
if item exist in List but not in ListTwo dont do anything yet save it
somewhere
continue from step 1
you are at the end of the List add the item(s) you skipped before in step
3
I know this much(actually I don't, I think I know), there are better ways to do this I'm sure
Why did I get downvote, did I miss something ?
It may be easier if you reverse the roles (store the keys in the ArrayList, in order) and the key-value mappings in a SortedMap, such as TreeMap, or ConcurrentSkipListMap. The comparator for the sorted map can use List.indexOf as the basis for element comparison.
With this arrangement, the map defines the key/value mapping, which is natural for the map, and the list maintains the desired order, which is quite natural for a List.
Alternatively, use a regular Map, and not a sorted map, and use iteration over the list, and fetching values from the map. E.g.
ArrayList keysList;
Map keyValues;
for(String key: keysList) {
String value = keyValues.get(key);
}
EDIT: Commons collections has SetUniqueList - a list that ensures uniqueness like a Set. It also has has various types of OrderedMap, in particular a ListOrderedMap that maintains the key/value mappings in the order of a list. For generics support, see commons collections with generics.
Use LinkedHashMap
You can call something like
map.put(one,value1);
and later call
map.get(one);
which will return value1
also a hash map does not accept duplicate key, so if you call
map.put(one,value2);
after this the original value is replaced.
you can use
map.containsKey(one)
to check whether one already exists as a key
If you are only comparing the keys of element then you can store them in LinkedHashSet and use the contains method of linkedHashset to check whether the element exists in constant time O(1).
LinkeHashMap also serves the purpose, however it requires extra space to store the value and this is not required we are only interested in keys.
Refer : http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html

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