Looping issue in for loop while avoiding duplicate entries - java

In selected contact i am having duplicate values so that iam first taking copy of selected contact copy
for(int q=0;q<selectedcontact.size();q++)
{
selectedcontactcopy.add(selectedcontact.get(q));
}
and then Comparing two array list
for(int r=0;r<selectedcontactcopy.size();r++)
{
for(int j=0;j<selectedcontact.size();j++)
{
if(r!=j && r<j)
{
if(selectedcontactcopy.get(r).getLandLineNumber().toString().trim().equals(selectedcontact.get(j).getLandLineNumber().toString().trim()))
{
Log.i("hai",selectedcontact.get(j).getLandLineNumber().toString());
selectedcontact.remove(j);
j--;
}
}
}
}
But the situation is that first duplication is avoided then the arraylist won't compare the next consecutive values

This is a bad way of doing a uniqueness check. A better method is to make use of the functionality of java.util.Set - make sure your contacts implement Comparable and compare landline numbers, and then add them to the set and iterate over the set contents.
Set guarantees you uniqueness, and provides a far cleaner interface than nested for loops.

Use HashSet to avoid repeated values from ArrayList,
Something like,
ArrayList arrayList = new ArrayList(); // Your ArrayList which contains repeated values
HashSet hashSet = new HashSet();
hashSet.addAll(arrayList);
arrayList.clear();
arrayList.addAll(hashSet);
The easiest way to remove repeated elements is to add the contents to a Set (which will not allow duplicates) and then add the Set back to the ArrayList.

there is no need to create 2 lists for this.
create a HashMap with keys as the landline number and value as the whole contact object.
iterate over the list 'selectedContacts' and put all the elements into the hashmap.
finally, iterate over the hashmap created and store all the values in the hashmap into a list of contacts.
hope it helps.

Related

Sorting a list after another one in Java

I need some help regarding list sorting. So, I have two lists, one which contains entities of type Sarcina(int Id,String desc) (lets call it ls1), and one which contains integers (lets call it ls2). Both lists have the same size. I am trying to sort both of them at the same time in descending order, interchanging the elements from the same positions in the both lists.
So, if I have ls1(Sarcina1,Sarcina2,Sarcina3) and ls2(3,5,4), and I sort ls2 as (5,4,3), I want to have in ls1 sorted as (Sarcina2,Sarcina3,Sarcina1).
Thank you.
You can use Treemap, Which maintains the sorted keys. Here you want to sort your Integers, so add them as keys and add your strings as values of a Treemap. It'll automatically sort it. So try someting like following:
TreeMap tm = new TreeMap();
// Put elements to the map
//Here "your_integer" is key and "your_string" is value in our Treemap
tm.put("your_integer","your_string");
tm.put("your_integer","your_string");
now tm is what you want. which has strings sorted according to your integers.

Cull all duplicates in a set

I'm using Set to isolate the unique values of a List (in this case, I'm getting a set of points):
Set<PVector> pointSet = new LinkedHashSet<PVector>(listToCull);
This will return a set of unique points, but for every item in listToCull, I'd like to test the following: if there is a duplicate, cull all of the duplicate items. In other words, I want pointSet to represent the set of items in listToCull which are already unique (every item in pointSet had no duplicate in listToCull). Any ideas on how to implement?
EDIT - I think my first question needs more clarification. Below is some code which will execute what I'm asking for, but I'd like to know if there is a faster way. Assuming listToCull is a list of PVectors with duplicates:
Set<PVector> pointSet = new LinkedHashSet<PVector>(listToCull);
List<PVector> uniqueItemsInListToCull = new ArrayList<PVector>();
for(PVector pt : pointSet){
int counter=0;
for(PVector ptCheck : listToCull){
if(pt==ptCheck){
counter++;
}
}
if(counter<2){
uniqueItemsInListToCull.add(pt);
}
}
uniqueItemsInListToCull will be different from pointSet. I'd like to do this without loops if possible.
You will have to do some programming yourself: Create two empty sets; on will contain the unique elements, the other the duplicates. Then loop through the elements of listToCull. For each element, check whether it is in the duplicate set. If it is, ignore it. Otherwise, check if it is in the unique element set. If it is, remove it there and add to the duplicates set. Otherwise, add it to the unique elements set.
If your PVector class has a good hashCode() method, HashSets are quite efficient, so the performance of this will not be too bad.
Untested:
Set<PVector> uniques = new HashSet<>();
Set<PVector> duplicates = new HashSet<>();
for (PVector p : listToCull) {
if (!duplicates.contains(p)) {
if (uniques.contains(p)) {
uniques.remove(p);
duplicates.add(p);
}
else {
uniques.add(p);
}
}
}
Alternatively, you may use a third-party library which offers a Bag or MultiSet. This allows you to count how many occurrences of each element are in the collection, and then at the end discard all elements where the count is different than 1.
What you are looking for is the intersection:
Assuming that PVector (terrible name by the way) implements hashCode() and equals() correctly a Set will eliminate duplicates.
If you want a intersection of the List and an existing Set create a Set from the List then use Sets.intersection() from Guava to get the ones common to both sets.
public static <E> Sets.SetView<E> intersection(Set<E> set1, Set<?> set2)
Returns an unmodifiable view of the intersection of two sets. The returned set contains all
elements that are contained by both backing sets. The iteration order
of the returned set matches that of set1. Results are undefined if
set1 and set2 are sets based on different equivalence relations (as
HashSet, TreeSet, and the keySet of an IdentityHashMap all are).
Note: The returned view performs slightly better when set1 is the
smaller of the two sets. If you have reason to believe one of your
sets will generally be smaller than the other, pass it first.
Unfortunately, since this method sets the generic type of the returned
set based on the type of the first set passed, this could in rare
cases force you to make a cast, for example:
Set aFewBadObjects = ... Set manyBadStrings =
...
// impossible for a non-String to be in the intersection
SuppressWarnings("unchecked") Set badStrings = (Set)
Sets.intersection(
aFewBadObjects, manyBadStrings); This is unfortunate, but should come up only very rarely.
You can also do union, complement, difference and cartesianProduct as well as filtering very easily.
So you want pointSet to hold the items in listToCull which have no duplicates? Is that right?
I would be inclined to create a Map, then iterate twice over the list, the first time putting a value of zero in for each PVector, the second time adding one to the value for each PVector, so at the end you have a map with counts. Now you're interested in the keys of the map for which the value is exactly equal to one.
It's not perfectly efficient - you're operating on list items more times than absolutely necessary - but it's quite clean and simple.
OK, here's the solution I've come up with, I'm sure there are better ones out there but this one's working for me. Thanks to all who gave direction!
To get unique items, you can run a Set, where listToCull is a list of PVectors with duplicates:
List<PVector> culledList = new ArrayList<PVector>();
Set<PVector> pointSet = new LinkedHashSet<PVector>(listToCull);
culledList.addAll(pointSet);
To go further, suppose you want a list where you've removed all items in listToCull which have a duplicate. You can iterate through the list and test whether it's in the set for each item. This let's us do one loop, rather than a nested loop:
Set<PVector> pointSet = new HashSet<PVector>(listToCull);
Set<PVector> removalList = new HashSet<PVector>();//list to remove
for (PVector pt : listToCull) {
if (pointSet.contains(pt)) {
removalList.add(pt);
}
else{
pointSet.add(pt);
}
}
pointSet.removeAll(removalList);
List<PVector> onlyUniquePts = new ArrayList<PVector>();
onlyUniquePts.addAll(pointSet);

Is there a list implementation that would allow gaps?

I'm looking for a collection that would be some sort of a list that allows gaps. The objectives are:
every element has some index in the collection that is meaningful.
the collection is to be sparse and not continuous; its size should return the number of proper elements, hence the workaround of initializing with null wouldn't work.
subList method is desirable to access sublists according to index intervals
Sample use case:
List<Integer> list = /* ? */;
list.add(0,5);
list.add(1,4);
list.add(5,3);
for( Integer i : list )
{
System.out.print( i + " " );
}
/* desired output : "5 4 3 "*/
Use a Map<Integer,Integer>. The key would be your index and the value the value of the list.
For your subList requirement, perhaps TreeMap<Integer,Integer> would work, as it keeps the keys sorted and makes it easy to iterate over a sub-list.
Of course this means you can't use the List interface. If you must use the List interface, you can make your own List implementation backed by a TreeMap (for example, list.add(5,3) would call map.put(5,3)).
You may use a Map and only set the keys you need.
You can keep the insertion order if you want, take a look: Java Class that implements Map and keeps insertion order

Creating a HashMap as an index for title keywords to improve search efficiency

I have a custom class Disks which stores various information of CDs such as their Title, Length, Artist etc. These Disks objects are stored in an ArrayList which can only have elements of Disks added. I am using a method to search for these objects based on matching their title. It takes a user input and then goes through each element of the list and compares the user keyword and the Title of the CD. If it is a complete match, its information is then returned to the user.
I want to change this search mechanization slightly by incorporating a HashMap. I am looking to tokenize each Disks Title and then create a mapping entry for the keyword.
Here is an example: The word "Cars" appears in the titles of the ArrayList elements at position 0,5,7. I want to be able to create a mapping entry for "Cars" which will be a list [0,5,7]. If another element is added to the ArrayList at position 10 with "Cars" in the title, how would I amend the old mapping entry so the new list would be [0,5,7,10]?
In the end I want the user to search for title keywords “Loud Cars”. I will first find "loud" in the index to get a list of [0,7,5] (for example), and then find "cars" to get a list of [0,5,7,10]. Then, I will find where these lists intersect and return the ArrayList elements that correspond to these locations.
My current HashMap declartion looks like this: public HashMap<String, ArrayList<Integer>> map = new HashMap<>(); however even when the Key is different, the values stored in the ArrayList are the same because there is only one of them.
My Disks ArrayList is: public ArrayList<Disks> items; Would there be a way to incorporate this ArrayList into the Value of the HashMap?
Add a new value to the index entry for "Cars"
map.get("Cars").add(10);
Safe way to do this (key = "Cars", index = 10):
ArrayList<Integer> entry = map.get(key);
if (entry == null) {
entry = new ArrayList<Integer>();
map.put(key, entry);
}
entry.add(index);
Instead of using
HashMap<String, ArrayList<Integer>>
I'd recommend
HashMap<String, HashSet<Integer>>
Which is automatically avoids duplicates.
When you search for multiple words, use retainAll to build the intersection of multiple sets (but copy the first set because retainAll is destructive):
Set<Integer> resultSet = new HashSet<Integer>();
resultSet.addAll(map.get("Cars"));
resultSet.retainAll(map.get("Loud"));
You would need to create a new ArrayList of Integer for every string mapping to a value. The first time an entry is used, you create a new list (You must check that the string maps to null), and add the value of the index that the new Disk entry will be stored at in your ArrayList of Disls to you ArrayList of Integers. Any time the string maps to a non-empty list, then you just add the index (where it is in the Disk ArrayList) to the ArrayList of Integer.
Honestly, I think the best way for you to scale your solution is by using bloom filters or something sophisticated like this. This would require you to create complex hash codes, manage false positives, among other things.
Having that said, based on your design, I think what you can simply have a hash map pointing to the Disks objects that are also stored on the array list.
public HashMap<String, ArrayList<Disks>> map
For the keyword "cars", you have a list of Disks objects. For the keyword "loud" you have another list of Disks objects. Just take both lists and find the intersection, using the retainAll() method.
Make sure to override hashCode() and equals() in Disks so all collections will work fine.

How To Prevent Duplicates In Object ArrayList

I have a custom object array list, the object must be in an array list however i have some duplicates in the list and i want to preform a check before i do an add to the list. How can this be achieved. The victimSocialSecurityNumber is unique. Under is my code:
CODE
while (rs.next()){
Citizens victims = new Citizens();
victims.setSocialSecurityNumber(rs.getInt("victimSocialSecurityNumber"));
victims.setfName(rs.getString("victimFName"));
victims.setlName(rs.getString("victimLName"));
victims.setPhoto(rs.getString("victimPhoto"));
victims.setName(rs.getString("victimFName") +" "+ rs.getString("victimLName"));
crime.getVictims().add(victims);
you can convert arraylist to set and back to get rid of the duplicates or use directly structure which allows only sorted unique elements : LinkedHashSet
Assuming Citizens overrides equals, you can do it like this
if (!crime.getVictims().contains(victims)) {
crime.getVictims().add(victims);
}
though generally when duplicates are not allowed the solution is Set
If you have doubts how to override equals / hashCode read http://javarevisited.blogspot.com/2011/10/override-hashcode-in-java-example.html
You can use a hash set to add the objects and convert it to an Arraylist. This can help you to check whether the victim is unique.
CODE
Set hashset = new HashSet();
while (rs.next()){
Citizens victims = new Citizens();
victims.setSocialSecurityNumber(rs.getInt("victimSocialSecurityNumber"));
victims.setfName(rs.getString("victimFName"));
victims.setlName(rs.getString("victimLName"));
victims.setPhoto(rs.getString("victimPhoto"));
victims.setName(rs.getString("victimFName") +" "+ rs.getString("victimLName"));
hashset.add(victims);
}
List list = new ArrayList(hashset);
I could be completely wrong here, but wouldn't a for loop solve your problem? You could just compare what you are about to add to all the elements in the arraylist, and if there are no matches add it, and if there is don't?

Categories