Is there any way to know what was the last new entries that were added to a hashset ? In my program the first cycle adds [Emmy, Carl] and than on my second cycle it adds [Emmy, Dan, Carl] is there anyway I can just use dan and not the rest of them for cycle three ?
java.util.HashSet does not preserve order, but java.util.LinkedHashSet does. Can you use that instead? From the Javadoc:
This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order). Note that insertion order is not affected if an element is re-inserted into the set.
HashSets do not carry information about the order in which you add elements. You need to replace it with a Collection that does (e.g. ArrayList).
Hashset are backed by hash tables and there is no guarantee on the order of retrieval. The order of retrieval will not be the same as the order of insertion. So, no it's not possible to know which item was added last.
Workarounds - may be use two hashsets, compare old with new and get the new entries or have some sort of indicators to distinguish the perticular iteration it was added or use ArrayList or anything that fits in your design.
HashSet<String> oldpeople = new HashSet<String>();P
HashSet<String> newPeople;
for (Set<String> cycle : input)
{
newPeople = new HashSet<String>();
newPeople.addAll(cycle);
newPeople.removeAll(oldPeople);
oldPeople.addAll(cycle);
}
now you have the last new one always contained in newPeople.
Well if I understand your post and the comments correctly (well that's quite hard, try to be bit more precise :) ) what you actually want is: a) not add any items several times to the HashSet and b) see if the set already contains the given item when trying to add it.
a) is trivially true for every set and for b) you can just use the return value of add: If it returns false is already contained in the set.
Related
Hi everyone please help, I discovered the NavigableMap today and initially it worked for me until I did the following.
When I populate the NavigableMap, notice from the end of the string value, I have added the values 1-4 and then 5.
The string layout is for example "23816012269<1>", the last value <#> makes this unique because I am using it later in the code.
All values up until 4 are duplicates (23816012269) , then 23806012269<5> is a new value prefixed with a different string/number and I will continue with new duplicates (suffixed with the next sequence <5> <#> number etc).
The problem is, when I populate the NavigableMap in the order that you see below, it puts ("238060122695",...) at the first entry of the NavigableMap, even though this was added to the NavigableMap very last.
Now when I use the NavigableMap.firstEntry().getKey() it reads "238060122695" as the first entry.
I need to read 238160122691 as the first entry because this was added to the map as the first entry.
Delving into the string value I know that 2380 comes before 2381, regardless, why does it treat it as the first entry when I added it last, is it because of the SortedMap interface that does this.? How do I avoid
This is code in the order being executed:
NavigableMap.put("238160122691", arrayListValue);
NavigableMap.put("238160122692", arrayListValue);
NavigableMap.put("238160122693", arrayListValue);
NavigableMap.put("238160122694", arrayListValue);
NavigableMap.put("238060122695", arrayListValue);
A NavigableMap is sorted:
A SortedMap extended with navigation methods returning the closest matches for given search targets. [...]
A NavigableMap may be accessed and traversed in either ascending or descending key order.
If you want entries to be in insertion order, use a LinkedHashMap:
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order).
Delving into the string value I know that 2380 comes before 2381, regardless, why does it treat it as the first entry when I added it last, is it because of the SortedMap interface that does this?
There seems to be a misunderstanding of what NavigableMap and its implementing classing like TreeMap are doing. They do not sort the elements in order of insertion, but by their natural order (i.e. how they compareTo each other), or given another Comparator.
How do I avoid?
Well, you could wrap your string keys into a data structure that also has a number showing when it was inserted into the map, and provide a Comparator or compareTo method that sorts by that number. But more likely, NavigableMap is just not the right data structure for you. Have you considered just using a List or Queue, or maybe a LinkedHashMap as suggested in comments.
Thank you All, I have moved back to the LinkedList as suggested by everyone.
I then found the use of the ListIterator to find the the next entry and stored that in a variable to compare to the next Iteration.
ListIterator<Map.Entry<String, ArrayList<DataModel>>> listIterator = new LinkedList(myHashMap.entrySet()).listIterator();
String previousk, nextk = null;
Boolean entered = false;
while (listIterator.hasNext())
{
if(entered){
previousk = nextk.substring(0,12);
if(previousk != nextk.substring(0,12)){
*Set the flag here to be used*
}
}
nextk = listIterator.next().getKey();
entered = true;
System.out.println(nextk);
}
I have data of which the sequence is as important as its unique elements. Meaning if something has already been added it should not be added again and the sequence must be remembered.
Set does not remember the sequence in which it was added (either hash or sort), and List is not unique.
What is the best solution to this problem?
Should one have a list and loop through it to test for uniqueness - which I'm trying to avoid?
Or should one have two collections, one a List and one a Set - which I'm also trying to avoid?
Or is there a different solution to this problem altogether.
In the bellow code was your reference
LinkedHashSet<String> al=new LinkedHashSet<String>();
al.add("guru");
al.add("karthik");
al.add("raja");
al.add("karthik");
Iterator<String> itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
output
guru
karthik
raja
Use LinkedHashSet. It serves as both a List and a Set. It has the uniqueness quality of a set but still remembers the order in which you inserted items to it which allows you to iterate it by order of insertion.
From the Docs:
Hash table and linked list implementation of the Set interface, with predictable iteration order. This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order). Note that insertion order is not affected if an element is re-inserted into the set. (An element e is reinserted into a set s if s.add(e) is invoked when s.contains(e) would return true immediately prior to the invocation.)
You can use SortedSet
or LinkedHashSet
LinkedHashSet is the best possible way out
I am learning to use sets. My question is : Sets do not contain duplicates. When we try to insert duplicates, it does not throw any error and automatically removes duplicates. Is it a good practice to check each value before inserting into set whether it exists or not? Or is it OK to do something like the below code? I think Java would be internally doing the check using .contains(value) . What do you think?
What would be the Big O complexity in both the cases considering there are n elements going into the set?
import java.util.HashSet;
import java.util.Set;
public class DuplicateTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Set<Integer> mySet = new HashSet<Integer>();
mySet.add(10);
mySet.add(20);
mySet.add(30);
mySet.add(40);
mySet.add(50);
mySet.add(50);
mySet.add(50);
mySet.add(50);
mySet.add(50);
mySet.add(50);
System.out.println("Contents of the Hash Set :"+mySet);
}
}
As per the docs:
public boolean add(E e)
Adds the specified element to this set if it is not already present. More formally, adds the specified element e to this set if this set contains no element e2 such that (e==null ? e2==null : e.equals(e2)). If this set already contains the element, the call leaves the set unchanged and returns false.
So the add() method already returns you a true or a false. So you don't need to do the additional check.
Compare with the API documentation of Set.add(E)
The add method checks if the element is already in the Set. If the element is already present, then the new element is not added, and the Set remains unchanged. In most situations, you don't need to check anything.
The complexity of the method depends of the concrete implementation of Set that you are using.
Its ok not to check. This is the main advantage over Sets of Lists, as they will automatically filter out duplicates.
HashSet has constant time performance (http://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html)
This class offers constant time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets
The add function returns a boolean which you can check to determine if the item was already in the Set. This is of course based on your needs and isn't a best practice. Its good to know that it will not remove an item that is already there so it can't be depended on to update the existing value with new information if you are defining equals based on surrogate keys from your database. This is opposite the way Maps work as a map will return any existing value and replace it with the new value.
Here are answers to your questions:
When we try to insert duplicates, it does not throw any error and
automatically removes duplicates.
Your understanding is not correct. The call to Set.add() will not add a new item if it is already in the set; this statement applies to all implementations of Set, including HashSet and TreeSet.
Is it a good practice to check each value before inserting into set
whether it exists or not? or is it okay to do something like the below
code? I think java would be internally doing the check using
.contains(value) . What do you think?
Because your understanding was incorrect from the start, then you do not need to check each value before inserting into the set to see if it already exists. Yes, internally, it is doing something like contains().
What would be the Big Oh complexity in both the cases considering
there are "n" elements going into the set?
For HashSet, the time complexity is O(1) for each add(). For TreeSet() -- which you didn't use -- the time complexity is O(lg N) for each add().
I am getting the unique elements from a arraylist into a hashset but it is being sorted by itself.But i need the data not to be in sorted order.How can it be done?
HashSet getting sorted
The items of a HashSet is not in a particular order at all, as explicitly stated in its javadoc:
It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.
Perhaps you meant to say that the items are "rearranged" in a different order than you have added the items and that this is undesireable.
In that case, just use LinkedHashSet instead of HashSet. It maintains the elements in insertion order.
Set<T> unique = new LinkedHashSet<T>(arrayList);
Or, perhaps, if you prefer automatic ordering based on the element's Comparable#compareTo() implementation or would like to supply a custom Comparator, then use a TreeSet instead.
Set<T> uniqueAndSorted = new TreeSet<T>(arrayList);
See also:
The Java Tutorials - Collecitons - Implementations
What do yo mean by 'I want data not in sorted order'? Do you mean to say that you want the same order in which it is present in the list?
If so, you can create a LinkedHashSet and add the entries from the arraylist.
eg:
ArrayList list = new ArrayList();
LinkedHashSet set = new LinkedHashSet();
for (String temp : list) {
set.add(temp);
}
This will ensure the same order in which the elements are present in the arraylist.
I have one Map that contains some names and numbers
Map<String,Integer> abc = new HashMap<String,Integer>();
It works fine. I can put some values in it but when I call it in different class it gives me wrong order. For example:
I putted
abc.put("a",1);
abc.put("b",5);
abc.put("c",3);
Iterator<String> iter = abc.keySet().iterator();
while (iter.hasNext()) {
String name = iter.next();
System.out.println(name);
}
some time it returns the order (b,a,c) and some time (a,c,b).
What is wrong with it? Is there any step that I am missing when I call this map?
Edit:
I changed to HashMap and result is still same
The only thing that's wrong is your expectations. The Map interface makes no guarantees about iteration order, and the HashMap implementation is based on hash functions which means the iteration order is basically random, and will sometimes change completely when new elements are added.
If you want a specific iteration order, you have thee options:
The SortedMap interfaces with its TreeMap implementation - these guarantee an iteration order according to the natural ordering of the keys (or an ordering imposed by a Comparator instance)
The LinkedHashMap class iterates in the order the elements were added to the map.
Use a List instead of a Map - this has a well-defined iteration order that you can influence in detail.
I think you need LinkedHashMap.
A TreeMap will always have keys in their natural order (unless you provide a comparator) If you are seeing the order any differently it will be the way you are looking at the map and what you are doing with it. If in doubt, use a debugger and you will see the order is sorted.
If you wish to get map values in the same order you used to insert them use LinkedHashMap instead.