I want to find something like ImmutableLinkedHashMap<> in Guava library.
I need to use an immutable key-value data structure with an insertion order.
So, what should I use?
I am not sure I am understanding exactly what you are after, but if it is a really immutable Map, you mght want to look at ImmutableMap
As mentioned in the doc:
An immutable, hash-based Map with reliable user-specified iteration order. Does not permit null keys or values.
Unlike Collections.unmodifiableMap(java.util.Map<? extends K, ? extends V>), which is a view of a separate map which can still change, an instance of ImmutableMap contains its own data and will never change. ImmutableMap is convenient for public static final maps ("constant maps") and also lets you easily make a "defensive copy" of a map provided to your class by a caller
E.g, you could use it in a similar fashion:
Map<Integer, String> m = ImmutableMap.of(5,"Five",6,"Six",7,"Seven");
Hope this is what you were after.
First create a LinkedHashMap and then use ImmutableMap.copyOf(linkedHashMap) to create an immutable copy which will have the same ordering as the original map.
Related
I know LinkedHashMap has a predictable iteration order (insertion order). Does the Set returned by LinkedHashMap.keySet() and the Collection returned by LinkedHashMap.values() also maintain this order?
The Map interface provides three
collection views, which allow a map's contents to be viewed as a set
of keys, collection of values, or set
of key-value mappings. The order of
a map is defined as the order in which
the iterators on the map's collection
views return their elements. Some map
implementations, like the TreeMap
class, make specific guarantees as to
their order; others, like the
HashMap class, do not.
-- Map
This linked list defines the iteration
ordering, which is normally the order
in which keys were inserted into the
map (insertion-order).
-- LinkedHashMap
So, yes, keySet(), values(), and entrySet() (the three collection views mentioned) return values in the order the internal linked list uses. And yes, the JavaDoc for Map and LinkedHashMap guarantee it.
That is the point of this class, after all.
Looking at the source, it looks like it does. keySet(), values(), and entrySet() all use the same entry iterator internally.
Don't get confused with LinkedHashMap.keySet() and LinkedHashMap.entrySet() returning Set and hence it should not guarantee ordering !
Set is an interface with HashSet,TreeSet etc beings its implementations. The HashSet implementation of Set interface does not guarantees ordering. But TreeSet does. Also LinkedHashSet does.
Therefore it depends on how Set has been implemented in LinkedHashMap to know whether the returning Set reference will guarantee ordering or not.
I went through the source code of LinkedHashMap, it looks like this:
private final class KeySet extends AbstractSet<K> {...}
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {...}
Thus LinkedHashMap/HashMap has its own implementation of Set i.e. KeySet. Thus don't confuse this with HashSet.
Also, the order is maintained by how the elements are inserted into the bucket. Look at the addEntry(..) method of LinkedHashMap and compare it with that of HashMap which highlights the main difference between HashMap and LinkedHashMap.
You can assume so. The Javadoc says 'predictable iteration order', and the only iterators available in a Map are those for the keySet(), entrySet(), and values().
So in the absence of any further qualification it is clearly intended to apply to all of those iterators.
AFAIK it is not documented so you cannot "formally" assume so. It is unlikely, however, that the current implementation would change.
If you want to ensure order, you may want to iterate over the map entires and insert them into a sorted set with an order function of your choice, though you will be paying a performance cost, naturally.
As we know that, SortedMap maintains the entries as sorted by keys. I read many threads in this forum and saw lots of example which sorts the SortedMap, by values. However, as you know when I put an item to default SortedMap it does not sort the Map again just put this new entry where it is supposed to be.
For example,
SortedMap<String,Person> sortedMap = new TreeMap();
Person p1 = new Person("John",38);
sortedMap.put(p1.getName(), p1);
Person p2 = new Person("Tom",34);
sortedMap.put(p2.getName(), p2); // does not sort, maintains sorted set by comparing the other values
Person p3 = new Person("Susan",21);
sortedMap.put(p3.getName(), p3); // does not sort, maintains sorted set by comparing the other values
In many threads in this forum, I saw many many code that sorts the SortedMap by values by calling a sort method like:
sortedMap.sort(sortedMap.entries());
This or something else method is being called to get values as sorted.
But, I need to a Map implementation which keeps the values as sorted without a calling sort method as I explained in above. For example, in above code I just can call the firstKey() method; but instead I need to call a firstValue() method.
Person minimumAgePerson = sortedMap.firstValue().
System.out.println(minimumAgePerson.getName()); // it should print "Susan"
SortedSet is not appropriate for my requiremenets because I can put some new Objects ( Person ) whose key values already in the map, these just added entries should override the existing objects ( so I need a map ):
Person p4 = new Person("Susan",39);
sortedMap.put(p4.getName(),p4);
Person newMinimumAgePerson = sortedMap.firstValue();
System.out.println(newMinimumAgePerson.getName()); // it should print "Tom"
Is there an implementation to accomplish this taks or do I need to implement SortedSet myself?
Often, the simplest and safest way of dealing with this type of problem is to write a class that uses two different standard collections. The class can offer exactly the methods you need, not necessarily conforming to any of the java.util interfaces.
Given the stated requirements, I would use a SortedMap to contain the values, combined with a HashMap mapping keys to values. To prevent duplicate keys, put the key-value pair in the HashMap, checking the put result. If the key was already present, remove the old value from the SortedMap before adding the new value.
If you have additional requirements, this particular design may not cover everything, but the concept of combining java.util structures is a generally useful one.
I think the best way for you is to create a custom type containing both a Map (for the key association), and a SortedSet (in order to sort values)
It is not clear to me if you want to be able to have the same value for two different keys. In this case, you'd need to use some kind of SortedMultiSet.
There is no implementation that contains a sort by both Key and Value. But really any implementation that did do this would need a separate datastructure for the sorting by value anyway, so you might as well create that datastructure yourself.
I would suggest either just implementing a sorted structure, using an existing one Like TreeMap or a PriorityQueue depending on your needs. Once that was done I would probably extend TreeMap with a custom structure and override the put,remove,addAll, etc methods to place it both in the super map, and also in your sort by keys structure.
I have an Android app in which I use a HashMap to store container objects. During the course of the App, the datastructure is accessed continuously.
However, about half the time, the reference used in not the Key in the map but another variable from the object so I end up looping over the structure again and again.
Is there an efficient way to have a datastructure indexed on two keys in Java ?
Why not two maps with different keys, but that both refer to the same values?
Manage two maps, where two sets of keys map to the same underlying set of objects. Wrap them in a class that has methods similar to a normal map, but internally searches on both keys, and synchronizes additions and deletions.
This is efficient because manipulations are (in the worst case) linearly proportionate to managing a single map.
I'd create a key object that combines the two variables.
You could use one map with both keys:
Map<Object, Person> personMap = new HashMap<Object, Person>()
Person person = ...
personMap.put(person.getName(), person)
personMap.put(person.getSSN(), person)
Then you can retrieve by the key. This of course assumes that there are no collisions in your key usage. If your two keys are different class types, then this is safe to do. If your keys are the same type (example String), then you may not want to use the two maps solution.
Follow-up: This approach does suffer from losing type safety, but it only impacts put(K, V) and putAll(Map<? extends K, ? extends V>), as get(Object) and containsKey(Object) always accepts Object.
So with this limitation I'd wrap this single map or go with the two map solution (also wrapped).
I have written some code that works fine but I am confused about the correct way to declare a TreeMap.
If SortedMap is a subinterface of Map then is it okay to just use Map if the code is working okay? Is SortedMap even necessary if TreeMap works fine with Map?
Should it be:
private Map<String, List <Bus>> map = new TreeMap<String, List <Bus>>();
or
private SortedMap<String, List <Bus>> map = new TreeMap<String, List <Bus>>();
Thanks.
Sorry this is so basic - I am new to Java.
I've used SortedMap to inform others that it is already sorted. Using Map is OK too.
private Map<String, List <Bus>> busTimetable = new TreeMap<String, List <Bus>>();
Unless you have a good reason, always use the highest level interface you can.
The answer to your question depends on your usage. By default, you should simply program to the data type's interface (i.e. Map). If SortedMap provides methods that you will be using that aren't declared in Map, then program to SortedMap.
If you need to use specific SortedMap methods (like firstKey()/lastKey()/whatever...), it is mandatory to declare your reference as SortedMap. Otherwise, Map is the one I'd choose, if I'm only planning on using it as a Map, so I'll be able so switch implementations without any other change in the code.
I agree with other commenters that you use SortedMap if you use methods that aren't in vanilla Map. Also use SortedMap if you have use in an iterator or a for-each loop if they implicitly rely on sorted input.
If neither of these cases are true, you should also think about if you only need a vanilla Map, a HashMap may be a better choice. HashMap has O(1) access; TreeMap does not.
It depends upon your requirement and design whenever possible use the highest level of abstraction that is Map. The reason is say you are creating a service and it consume list of data and produce an output in a Map.
some client may expect for sorted order of the data in the map and some other client may just need the data in the insertion order of the map if you use a specific interface SortedMap ; this kind of scenarion you can not handle using one service and you will end up creating two different api becuase one who is expecting sorted order you can just return an implementaion of TreeMap and one for insertion order you can use LinkedHashMap. So it's about how flexible is your program.
I'm looking for a way to maintain the sorting on my key-value pairs. They are sorted by variables outside of the actual key-value pairs (for better UI). I am currently using a Hashtable, but that does not maintain the sorting =(
Hashtable<Integer, String> subscriptions = getUsersSubscriptions(user);
Is there some simple way that Java lets one store pairs? The best idea I can think of is using 2 associated ArrayLists (one of type Integer, another of type String). Can someone think of something better?
If your key-value pairs are already sorted, LinkedHashMap will maintain order of insertion.
In other words, the keys returned by map.keySet() will be in the exact order you put them into the map.
SortedMap<Integer, String> myMap = new TreeMap<Integer,String>();
If you have a custom sorting, pass a Comparator instance to the constructor of the TreeMap. But be careful doing so, as using a Comparator that does not go well with natural Integer order would make things impossible to understand and debug.
LinkedHashMap can be used here.
Is there some simple way that Java lets one store pairs?
Create a custom class that stores the two properties.
They are sorted by variables outside of the actual key-value pairs
Add a third property for the sort data.
Then your class can implement Comparable to sort the data as required based on this property.
Or you can use a custom Comparator to sort on the sort data field.
Now the class instances can be stored in an ArrayList.