Is Set sorted in some manner by default? - java

I have this set with elements added in the given order.
Set<String> nations = new HashSet<String>();
nations.add("Australia");
nations.add("Japan");
nations.add("Taiwan");
nations.add("Cyprus");
nations.add("Cuba");
nations.add("India");
When I print the record -
for (String s : nations) {
System.out.print(s + " ");
}
It always gives this output in the order
Cuba Cyprus Japan Taiwan Australia India
As far as I know a Set is not sorted by default, but why do I get the same result in a particular sorted manner?
Update : Here is the actual question -
public static Function<String,String> swap = s -> {
if(s.equals("Australia"))
return "New Zealand";
else
return s;
};
Set<String> islandNations = Set.of("Australia", "Japan", "Taiwan", "Cyprus", "Cuba");
islandNations = islandNations.stream()
.map(swap)
.map(n -> n.substring(0, 1))
.collect(Collectors.toSet());
for(String s : islandNations){
System.out.print(s);
}
and answers one of these
CTJN
TJNC
TCNJ

HashSet's documentation says:
It makes no guarantees as to the iteration order of the set.
No guarantees means no guarantees. For example, it could be sorted order, reverse sorted order, random order, or sorted order except on Tuesdays when it's random.
(In practice, the iteration order is usually always the same for the same Java version, or at least for the same run of the JVM, and that order is produced by a deliberately convoluted algorithm based on the hash codes of the elements. However, if you depend on that behavior, it will usually change at the worst possible time.)

HashSet does not preserve the order of insertion of elements, as the order is maintained based on the hashing mechanism like Map because the add() method internally inserts the element as a key in a Map.
HashSet
//add method implementation for HashSet
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
here, map is a private transient HashMap<E,Object> map;
As the map is HashMap here, so no sorting will be done.
TreeSet
//add method implementation for TreeSet
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
here, map is a private transient NavigableMap<E,Object> m;
As the map is NavigableMap here, so sorting will be done.

The HashSet uses the hash value of each element for storage.
The important points about Java HashSet class are:
HashSet stores the elements by using a mechanism called hashing.
HashSet contains unique elements only.
HashSet allows null value.
HashSet class is non-synchronized.
HashSet doesn't maintain the insertion order. Here, elements are inserted on the basis of their hashcode.
HashSet is the best approach for search operations.
The initial default capacity of HashSet is 16, and the load factor is 0.75.
if you need to store (and display) in the order you can use the SortedSet interface, like this:
SortedSet<String> orderedList = new TreeSet<String>();
orderedList.add("C");
orderedList.add("D");
orderedList.add("E");
orderedList.add("A");
orderedList.add("B");
orderedList.add("Z");
for (String value : orderedList)
System.out.print(value + ", ");
Output:
A, B, C, D, E, Z,
Remembering: SortedSet uses the Comparable interface and the compareTo() method to sort the String values. If you have a customized class you should implement this interface/method to use in this approach.
Or, you can define the comparator that must be used:
SortedSet<Person> persons = new TreeSet<>Comparator.comparing(Person::getName));

Related

LinkedHashSet - insertion order and duplicates - keep newest "on top"

I need a collection that keeps insertion order and has unique values. LinkedHashSet looks like the way to go, but there's one problem - when two items are equal, it removes the newest one (which makes sense), here's an example:
set.add("one");
set.add("two");
set.add("three");
set.add("two");
The LinkedHashSet will print:
one, two, three
But what I need is:
one, three, two
What would be the best solution here? Is there any collection/collections method that can do this or should I implement it manually?
Most of the Java Collections can be extended for tweaking.
Subclass LinkedHashSet, overriding the add method.
class TweakedHashSet<T> extends LinkedHashSet<T> {
#Override
public boolean add(T e) {
// Get rid of old one.
boolean wasThere = remove(e);
// Add it.
super.add(e);
// Contract is "true if this set did not already contain the specified element"
return !wasThere;
}
}
You can simply use a special feature of LinkedHashMap:
Set<String> set = Collections.newSetFromMap(new LinkedHashMap<>(16, 0.75f, true));
set.add("one");
set.add("two");
set.add("three");
set.add("two");
System.out.println(set); // prints [one, three, two]
In Oracle’s JRE the LinkedHashSet is backed by a LinkedHashMap anyway, so there’s not much functional difference, but the special constructor used here configures the LinkedHashMap to change the order on every access not only on insertion. This might sound as being too much, but in fact affects the insertion of already contained keys (values in the sense of the Set) only. The other affected Map operations (namely get) are not used by the returned Set.
If you’re not using Java 8, you have to help the compiler a bit due to the limited type inference:
Set<String> set
= Collections.newSetFromMap(new LinkedHashMap<String, Boolean>(16, 0.75f, true));
but the functionality is the same.
When initializing you're LinkedHashSet you could override the add method.
Set<String> set = new LinkedHashSet<String>(){
#Override
public boolean add(String s) {
if(contains(s))
remove(s);
return super.add(s);
}
};
Now it gives you:
set.add("1");
set.add("2");
set.add("3");
set.add("1");
set.addAll(Collections.singleton("2"));
// [3, 1 ,2]
even the addAll method is working.
All solution provided above are excellent but if we don't want to override already implemented collections. We can solve this problem simply by using an ArrayList with a little trick
We can create a method which you will use to insert data into your list
public static <T> void addToList(List<T> list, T element) {
list.remove(element); // Will remove element from list, if list contains it
list.add(element); // Will add element again to the list
}
And we can call this method to add element to our list
List<String> list = new ArrayList<>();
addToList(list, "one");
addToList(list, "two");
addToList(list, "three");
addToList(list, "two");
Only disadvantage here is we need to call our custom addToList() method everytime instead of list.add()

How to sort a HashSet?

For lists, we use the Collections.sort(List) method. What if we want to sort a HashSet?
A HashSet does not guarantee any order of its elements. If you need this guarantee, consider using a TreeSet to hold your elements.
However if you just need your elements sorted for this one occurrence, then just temporarily create a List and sort that:
Set<?> yourHashSet = new HashSet<>();
...
List<?> sortedList = new ArrayList<>(yourHashSet);
Collections.sort(sortedList);
Add all your objects to the TreeSet, you will get a sorted Set. Below is a raw example.
HashSet myHashSet = new HashSet();
myHashSet.add(1);
myHashSet.add(23);
myHashSet.add(45);
myHashSet.add(12);
TreeSet myTreeSet = new TreeSet();
myTreeSet.addAll(myHashSet);
System.out.println(myTreeSet); // Prints [1, 12, 23, 45]
Update
You can also use TreeSet's constructor that takes a HashSet as a parameter.
HashSet myHashSet = new HashSet();
myHashSet.add(1);
myHashSet.add(23);
myHashSet.add(45);
myHashSet.add(12);
TreeSet myTreeSet = new TreeSet(myHashSet);
System.out.println(myTreeSet); // Prints [1, 12, 23, 45]
Thanks #mounika for the update.
Java 8 way to sort it would be:
fooHashSet.stream()
.sorted(Comparator.comparing(Foo::getSize)) //comparator - how you want to sort it
.collect(Collectors.toList()); //collector - what you want to collect it to
*Foo::getSize it's an example how to sort the HashSet of YourItem's naturally by size.
*Collectors.toList() is going to collect the result of sorting into a List the you will need to capture it with List<Foo> sortedListOfFoo =
You can use a TreeSet instead.
Use java.util.TreeSet as the actual object. When you iterate over this collection, the values come back in a well-defined order.
If you use java.util.HashSet then the order depends on an internal hash function which is almost certainly not lexicographic (based on content).
Just in-case you don't wanna use a TreeSet you could try this using java stream for concise code.
set = set.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new));
You can use Java 8 collectors and TreeSet
list.stream().collect(Collectors.toCollection(TreeSet::new))
Based on the answer given by #LazerBanana i will put my own example of a Set sorted by the Id of the Object:
Set<Clazz> yourSet = [...];
yourSet.stream().sorted(new Comparator<Clazz>() {
#Override
public int compare(Clazz o1, Clazz o2) {
return o1.getId().compareTo(o2.getId());
}
}).collect(Collectors.toList()); // Returns the sorted List (using toSet() wont work)
Elements in HashSet can't be sorted. Whenever you put elements into HashSet, it can mess up the ordering of the whole set. It is deliberately designed like that for performance. When you don't care about the order, HashSet will be the most efficient set for frequent insertions and queries.
TreeSet is the alternative that you can use. When you iterate on the tree set, you will get sorted elements automatically.
But it will adjust the tree to try to remain sorted every time you insert an element.
Perhaps, what you are trying to do is to sort just once. In that case, TreeSet is not the most efficient option because it needs to determine the placing of newly added elements all the time. Use TreeSet only when you want to sort often.
If you only need to sort once, use ArrayList. Create a new list and add all the elements then sort it once. If you want to retain only unique elements (remove all duplicates), then put the list into a LinkedHashSet, it will retain the order you have already sorted.
List<Integer> list = new ArrayList<>();
list.add(6);
list.add(4);
list.add(4);
list.add(5);
Collections.sort(list);
Set<Integer> unique = new LinkedHashSet<>(list); // 4 5 6
Now, you've gotten a sorted set if you want it in a list form then convert it into list.
You can use TreeSet as mentioned in other answers.
Here's a little more elaboration on how to use it:
TreeSet<String> ts = new TreeSet<String>();
ts.add("b1");
ts.add("b3");
ts.add("b2");
ts.add("a1");
ts.add("a2");
System.out.println(ts);
for (String s: ts)
System.out.println(s);
Output:
[a1, a2, a3, a4, a5]
a1
a2
b1
b2
b3
In my humble opinion , LazerBanana's answer should be the top rated answer & accepted because all the other answers pointing to java.util.TreeSet ( or first convert to list then call Collections.sort(...) on the converted list ) didn't bothered to ask OP as what kind of objects your HashSet has i.e. if those elements have a predefined natural ordering or not & that is not optional question but a mandatory question.
You just can't go in & start putting your HashSet elements into a TreeSet if element type doesn't already implement Comparable interface or if you are not explicitly passing Comparator to TreeSet constructor.
From TreeSet JavaDoc ,
Constructs a new, empty tree set, sorted according to the natural
ordering of its elements. All elements inserted into the set must
implement the Comparable interface. Furthermore, all such elements
must be mutually comparable: e1.compareTo(e2) must not throw a
ClassCastException for any elements e1 and e2 in the set. If the user
attempts to add an element to the set that violates this constraint
(for example, the user attempts to add a string element to a set whose
elements are integers), the add call will throw a ClassCastException.
That is why only all Java8 stream based answers - where you define your comparator on the spot - only make sense because implementing comparable in POJO becomes optional. Programmer defines comparator as and when needed. Trying to collect into TreeSet without asking this fundamental question is also incorrect ( Ninja's answer). Assuming object types to be String or Integer is also incorrect.
Having said that, other concerns like ,
Sorting Performance
Memory Foot Print ( retaining original set and creating new sorted sets each time sorting is done or wish to sort the set in - place etc etc )
should be the other relevant points too. Just pointing to API shouldn't be only intention.
Since Original set already contains only unique elements & that constraint is also maintained by sorted set so original set needs to be cleared from memory since data is duplicated.
1. Add all set element in list -> al.addAll(s);
2. Sort all the elements in list using -> Collections.sort(al);
public class SortSetProblem {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList();
Set<String> s = new HashSet<>();
s.add("ved");
s.add("prakash");
s.add("sharma");
s.add("apple");
s.add("ved");
s.add("banana");
System.out.println("Before Sorting");
for (String s1 : s) {
System.out.print(" " + s1);
}
System.out.println("After Sorting");
al.addAll(s);
Collections.sort(al);
for (String set : al) {
System.out.print(" " + set);
}
}
}
input - ved prakash sharma apple ved banana
Output - apple banana prakash sharma ved
If you want want the end Collection to be in the form of Set and if you want to define your own natural order rather than that of TreeSet then -
Convert the HashSet into List
Custom sort the List using Comparator
Convert back the List into LinkedHashSet to maintain order
Display the LinkedHashSet
Sample program -
package demo31;
import java.util.*;
public class App26 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
addElements(set);
List<String> list = new LinkedList<>();
list = convertToList(set);
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
int flag = s2.length() - s1.length();
if(flag != 0) {
return flag;
} else {
return -s1.compareTo(s2);
}
}
});
Set<String> set2 = new LinkedHashSet<>();
set2 = convertToSet(list);
displayElements(set2);
}
public static void addElements(Set<String> set) {
set.add("Hippopotamus");
set.add("Rhinocerous");
set.add("Zebra");
set.add("Tiger");
set.add("Giraffe");
set.add("Cheetah");
set.add("Wolf");
set.add("Fox");
set.add("Dog");
set.add("Cat");
}
public static List<String> convertToList(Set<String> set) {
List<String> list = new LinkedList<>();
for(String element: set) {
list.add(element);
}
return list;
}
public static Set<String> convertToSet(List<String> list) {
Set<String> set = new LinkedHashSet<>();
for(String element: list) {
set.add(element);
}
return set;
}
public static void displayElements(Set<String> set) {
System.out.println(set);
}
}
Output -
[Hippopotamus, Rhinocerous, Giraffe, Cheetah, Zebra, Tiger, Wolf, Fox, Dog, Cat]
Here the collection has been sorted as -
First - Descending order of String length
Second - Descending order of String alphabetical hierarchy
you can do this in the following ways:
Method 1:
Create a list and store all the hashset values into it
sort the list using Collections.sort()
Store the list back into LinkedHashSet as it preserves the insertion order
Method 2:
Create a treeSet and store all the values into it.
Method 2 is more preferable because the other method consumes lot of time to transfer data back and forth between hashset and list.
We can not decide that the elements of a HashSet would be sorted automatically. But we can sort them by converting into TreeSet or any List like ArrayList or LinkedList etc.
// Create a TreeSet object of class E
TreeSet<E> ts = new TreeSet<E> ();
// Convert your HashSet into TreeSet
ts.addAll(yourHashSet);
System.out.println(ts.toString() + "\t Sorted Automatically");
You can use guava library for the same
Set<String> sortedSet = FluentIterable.from(myHashSet).toSortedSet(new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
// descending order of relevance
//required code
}
});
SortedSet has been added Since java 7
https://docs.oracle.com/javase/8/docs/api/java/util/SortedSet.html
You can wrap it in a TreeSet like this:
Set mySet = new HashSet();
mySet.add(4);
mySet.add(5);
mySet.add(3);
mySet.add(1);
System.out.println("mySet items "+ mySet);
TreeSet treeSet = new TreeSet(mySet);
System.out.println("treeSet items "+ treeSet);
output :
mySet items [1, 3, 4, 5]
treeSet items [1, 3, 4, 5]
Set mySet = new HashSet();
mySet.add("five");
mySet.add("elf");
mySet.add("four");
mySet.add("six");
mySet.add("two");
System.out.println("mySet items "+ mySet);
TreeSet treeSet = new TreeSet(mySet);
System.out.println("treeSet items "+ treeSet);
output:
mySet items [six, four, five, two, elf]
treeSet items [elf, five, four, six, two]
requirement for this method is that the objects of the set/list should be comparable (implement the Comparable interface)
The below is my sample code and its already answered by pointing the code in comments , am still sharing because it contains the complete code
package Collections;
import java.util.*;
public class TestSet {
public static void main(String[] args) {
Set<String> objset = new HashSet<>();
objset.add("test");
objset.add("abc");
objset.add("abc");
objset.add("mas");
objset.add("vas");
Iterator itset = objset.iterator();
while(itset.hasNext())
{
System.out.println(itset.next());
}
TreeSet<String> treeobj = new TreeSet(objset);
System.out.println(treeobj);
}
}
TreeSet treeobj = new TreeSet(objset); here we are invoking the treeset constructor which will call the addAll method to add the objects .
See this below code from the TreeSet class how its mentioned ,
public TreeSet(Collection<? extends E> c) {
this();
addAll(c);
}
Convert HashSet to List then sort it using Collection.sort()
List<String> list = new ArrayList<String>(hset);
Collections.sort(List)
This simple command did the trick for me:
myHashSet.toList.sorted
I used this within a print statement, so if you need to actually persist the ordering, you may need to use TreeSets or other structures proposed on this thread.

How to retrieve elements from sorted TreeSet using Binary Search?

I am trying to merge multiple sorted lists into one TreeSet.. And then I am thinking to apply Binary Search algorithm on that TreeSet to retrieve the element in O(log n) time complexity..
Below is my code in which I am passing List of Lists in in one of my method and combining them into TreeSet to avoid duplicacy... All the lists inside inputs are sorted -
private TreeSet<Integer> tree = new TreeSet<Integer>();
public void mergeMultipleLists(final List<List<Integer>> inputs) {
tree = new TreeSet<Integer>();
for (List<Integer> input : inputs) {
for(Integer ii : input) {
tree.add(ii);
}
}
}
public List<Integer> getItem(final Integer x) {
// extract elements from TreeSet in O(log n)
}
First of all, is this right way to merge multiple sorted lists into TreeSet? Is there any direct way to merge multiple sorted lists in TreeSet efficiently?
Secondly, how would I extract an element from that TreeSet in O(log n) time complexity? I would like to find an element x in that TreeSet, if it is there, then return it, if it is not there then return the next largest value from the TreeSet.
Or may be I am better off to another data structure as compared to which I am using currently?
UPDATED CODE:-
private TreeSet tree = new TreeSet();
public SearchItem(final List<List<Integer>> inputs) {
tree = new TreeSet<Integer>();
for (List<Integer> input : inputs) {
tree.addAll(input);
}
}
public Integer getItem(final Integer x) {
if(tree.contains(x)) {
return x;
} else {
// now how do I extract next largest
// element from it if x is not present
}
}
TreeSet is backed by a NavigableMap, a TreeMap specifically. Calling contains() on a TreeSet delegates to TreeMap.containsKey(), which is a binary search implementation.
You can check if an object is contained in the set by using TreeSet.contains(), but you have to have the object first. If you want to be able to look up and retrieve an object, then a Map implementation will be better.
You could use TreeSet.floor(), which according to the docs
Returns the greatest element in this set less than or equal to the given element, or null if there is no such element.
TreeSet, by it's nature is a sorted set and uses a red-tree-black-tree via TreeMap as it's backing
Basically: TreeSet.add(E) -> TreeMap.put(E,NULL);
As it is already a binary, sorted tree structure any 'get' or 'contains' will result in an O(log n) operation.
Your code and your question though don't line up.
You're flattening a List<List<Integer>> and just putting them all in to get all unique elements (or, at least, that's what this code will do).
But then your following method says "given this integer, give me a List<Integer>" which isn't achievable in the above code
So, let me answer your questions in order:
Sure/Yes Y
No. You misunderstand Sets (you can't extract by design) If you can do Set.contains(e)
then you HAVE the element and need not extract anything
If you need to do something like a "Set extraction" then use a TreeMap or turn your set back into a list and do myList.get(Collections.binarySearch(myElement));

Finding the key whose value is the lowest value in a hashmap

I'm trying to come up with an efficient way to return a key in my HashMap that has the lowest value in datastructure. Is there a quick and efficient way to do this besides looping through the entire HashMap?
For example, if I have a hashmap that looks like this:
1: 200
3: 400
5: 1
I want to return the key, 5.
No, you have to loop over all the keys in a HashMap to find the smallest. If this is an important operation, you're better off using a SortedMap, for instance TreeMap, which keeps its elements in sorted order, and then you can simply call firstKey() to find the lowest key.
As others have mentioned HashMap itself does not provide this.
So your options are to either compute it on-demand or pre-compute.
To compute it on-demand, you would iterate the HashMap.entrySet()
Depending on the size of the map, frequency of its change and frequency of requiring the key-with-lowest-value, pre-computing (caching) may be more efficient. Something as follows:
class HashMapWithLowestValueCached<K, V extends Comparable> extends HashMap<K, V> {
V lowestValue;
K lowestValueKey;
void put(K k, V v) {
if (v.compareTo(lowestValue) < 0) {
lowestValue = v;
lowestValueKey = k;
}
super.put(k, v);
}
K lowestValueKey () { return lowestValueKey; }
}
No, there is no way of doing this. You need to iterate over all the elements in the HashMap to find the one with the lowest value.
The reason why we have different kinds of storage is that they support different kinds of operations with different efficiency. HashMap is not designed to retrieve elements efficienctly based on their value. The kind of storage class you need for this will depend on what other operations you need to be able to do quickly. Assuming that you probably also want to be able to retrieve items quickly based on their key, the following might work:
Write a wrapper around your HashMap that keeps track of all the elements being added to it, and remembers which oneis the smallest. This is really only useful if retriving the smalls is the only way you need to access by value.
Store all your data twice - once in a HashMap and once in a data structure that sorts by value - for example, a SortedMap with key and value reversed.
If you find you don't need to retrieve by key, just reverse key and value.
No, there is no quick and efficient way of doing that - you need to loop through the entire hash map. The reason for it is that the keys and values in hash maps do not observe any particular order.
No, because otherwise there would exist a sorting algorithm in O(n log n) (probabilistic, though): add all elements to the hash map, than extract the lowest one by one.
//create hashmap
HashMap<Integer, String> yourHashmap = new HashMap<>();
//add your values here
yourHashmap.put(1,"200");
yourHashmap.put(3,"400");
yourHashmap.put(5,"1");
//then create empty arraylist
ArrayList<Integer> listDuplicates = new ArrayList<Integer>();
//filing the empty arraylist with all id's from duplicateHashmap
for (Map.Entry<Integer, String> entry : yourHashmap.entrySet()) {
listDuplicates.add(entry.getKey());
}
//Ordering the numbers
Collections.sort(listDuplicates);
for (Integer num : listDuplicates) {
int id = num; //entry
String number2 = duplicateHashmap.get(num);//value
System.out.println("lowest value = "+id+" : "+number2);
//breaking here because we've found the lowest value...
break;
}

How to get element position from Java Map

I have this Java Map:
Can you tell me how I can get the 6-th element of the Map?
private static final Map<String, Users> cache = new HashMap<>();
is this possible? Or I have to use another Java collection?
Though a bit late to answer. But the option is to use LinkedHashMap: this map preserves the order according to insertion of elements, as everyone has suggested. However, As a warning, it has a constructor LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) which will create a linked hash map whose order of iteration is the order in which its entries were last accessed. Don't use this constructor for this case.
However, if I needed such functionality, i would extend it and implement my necessary function to re-use them in OOP way.
class MyLinkedMap<K, V> extends LinkedHashMap<K, V>
{
public V getValue(int i)
{
Map.Entry<K, V>entry = this.getEntry(i);
if(entry == null) return null;
return entry.getValue();
}
public Map.Entry<K, V> getEntry(int i)
{
// check if negetive index provided
Set<Map.Entry<K,V>>entries = entrySet();
int j = 0;
for(Map.Entry<K, V>entry : entries)
if(j++ == i)return entry;
return null;
}
}
Now i can instantiate it and can get a entry and value either way i want:
MyLinkedMap<String, Integer>map = new MyLinkedMap<>();
map.put("a first", 1);
map.put("a second", 2);
map.put("a third", 3);
System.out.println(map.getValue(2));
System.out.println(map.getEntry(1));
Output:
3
a second=2
HashMap doesn't grantee the order. If you concern about order you should use LinkedHashMap
Map<String, Users> orderedMap=new LinkedHashMap<>();
Now when you put an element it will keep the order what you put.
If you want to get 6th element, now you can do it since you have your elements in order.
orderedMap.values().toArray()[5]// will give you 6th value in the map.
Example
Map<String, String> orderedMap=new LinkedHashMap<>();
orderedMap.put("a","a");
orderedMap.put("b","b");
System.out.println(orderedMap.values().toArray()[1]); // you will get b(value)
System.out.println(orderedMap.keySet().toArray()[1]); // you will get b(key)
}
A HashMap does not maintain the order of the elements inserted in it. You can used a LinkedHashMap instead which maintains the order of the elements inserted in it.
Though you need to note that even a LinkedHashMap has no such method which would give the element at a particular index. You will have to manually iterate through the entries and extract the element at the 6th iteration.
With guava's Iterables
Iterables.get(map.entrySet(),6);
The HashMap has no defined ordering of keys.It's Unordered.
You can use LinkedHashMap which will store your keys in order of insertion.You can retrieve them by calling keySet().
HashMaps do not preserve ordering:
LinkedHashMap which guarantees a predictable iteration order.
Example
public class Users
{
private String Id;
public String getId()
{
return Id;
}
public void setId(String id)
{
Id = id;
}
}
Users user;
LinkedHashMap<String,Users> linkedHashMap = new LinkedHashMap<String,Users>();
for (int i = 0; i < 3; i++)
{
user = new Users();
user.setId("value"+i);
linkedHashMap.put("key"+i,user);
}
/* Get by position */
int pos = 1;
Users value = (new ArrayList<Users>(linkedHashMap.values())).get(pos);
System.out.println(value.getId());
According to documentation, HashMap is a Hash table based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.) 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.
That's why it is not wise to use this kind of Collection.
UPDATE:
Based on #Prateek implementation of LinkedHashMap I would suggest something like:
LinkedHashMap<String,User> linkedHashMap = new LinkedHashMap<String,User>();
// or LinkedHashMap<String,User> linkedHashMap = new LinkedHashMap<>(); //for java 7+
linkedHashMap.put("1",userObj1);
linkedHashMap.put("2",userObj2);
linkedHashMap.put("3",userObj3);
/* Get by position */
int pos = 1; // Your position
User tmp= (new ArrayList<User>(linkedHashMap.values())).get(pos);
System.out.println(tmp.getName());
A HashMap doesn't have a position. You can iterate through its KeySet or EntrySet, and pick the nth element, but it's not really the same as a position. A LinkedHashMap does have a position, since it has a predictable iteration order.
You need to use a LinkedHashMap in order to be able to tell the order of the inserted elements. HashMap is not capable of doing so.
There is no Order in HashMap. You can obtain the list of may keys using map.keySet() but there's no guarantee the key set will be in the order which you add it in. Use LinkedHashMap instead of HashMap It will always return keys in same order (as insertion)
Correct!!
you will have to use other collection for getting values on index(position).
You can use ArrayList
If the ordering is to mean anything significant, you could consider using a SortedMap.
Concrete implementation: TreeMap
Use LinkedHashMap instead of HashMap It will return keys in same order (as insertion) when calling keySet().
For mare detail about LinkedHashMap see this
For example to get the element from specific index
Create a new list from your values and get the value based on index.
LinkedHashMap<String, List<String>> hMap;
List<List<String>> l = new ArrayList<List<String>>(hMap.values());
l.get(6);

Categories

Resources