Removing duplicate Sets from List - java

I am trying to remove duplicate Set of custom objects from ArrayList. Below is the code I have written which uses toString representation of custom EmployeeObj to compare. Can you please suggest what other approaches can be taken?
package com.collections;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class DupSetInsideList {
public static void main(String[] args) {
List<Set<EmployeeObj>> list = new ArrayList<Set<EmployeeObj>>();
Set<EmployeeObj> set1 = new HashSet<EmployeeObj>();
Set<EmployeeObj> set2 = new HashSet<EmployeeObj>();
Set<EmployeeObj> set3 = new HashSet<EmployeeObj>();
list.add(set1);
list.add(set2);
list.add(set3);
EmployeeObj empObj1 = new EmployeeObj(1, "Nikhil");
EmployeeObj empObj2 = new EmployeeObj(2, "Rakesh");
EmployeeObj empObj3 = new EmployeeObj(3, "Kunal");
set1.add(empObj1);
set1.add(empObj2);
set2.add(empObj1);
set2.add(empObj2);
set3.add(empObj1);
set3.add(empObj2);
set3.add(empObj3);
System.out.println("List with duplicaes: " + list);
//Output: List with duplicaes: [[1=Nikhil, 2=Rakesh], [1=Nikhil, 2=Rakesh], [3=Kunal, 1=Nikhil, 2=Rakesh]]
//Remove duplicates
List<Set<EmployeeObj>> nonDupList = new ArrayList<Set<EmployeeObj>>();
for(Set<EmployeeObj> obj1:list) {
if(!nonDupList.contains(obj1)) {
nonDupList.add(obj1);
}
}
System.out.println("List without duplicates: " + nonDupList);
//List without duplicates: [[1=Nikhil, 2=Rakesh], [3=Kunal, 1=Nikhil, 2=Rakesh]]
}
}
class EmployeeObj {
private int id;
private String name;
public int getId() {
return id;
}
public String getName() {
return name;
}
public EmployeeObj(int id, String name) {
this.id = id;
this.name = name;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EmployeeObj other = (EmployeeObj) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
#Override
public String toString() {
return id + "=" + name;
}
}

If you want a list behaviour guaranteeing a uniqueness of elements use a LinkedHashSet instead of ArrayList.
If you are bound to using ArrayList (as in a student exercise), extend it, overwrite add and addAll methods by checking the uniqueness first and then calling super.add resp. super.addAll and then use the new class in place of ArrayList.

The Set interface specifies the equals method as follows:
Compares the specified object with this set for equality. Returns true if the specified object is also a set, the two sets have the same size, and every member of the specified set is contained in this set (or equivalently, every member of this set is contained in the specified set).
So in order to create a list that contains no duplicates (even if the elements in the list are sets), one can simply write
//Remove duplicates
List<Set<EmployeeObj>> nonDupList =
new ArrayList<Set<EmployeeObj>>(
new LinkedHashSet<Set<EmployeeObj>>(list));

Try this solution:
private boolean equals(Set elements, Set elements2) {
return elements != null && elements.equals(elements2);
}
private List<Set> removeDuplicates(List<Set> from) {
List<Set> noDuplicates = new ArrayList<Set>();
for (Set possibleDuplicate : from) {
boolean alreadyInNoDuplicatesList = false;
for (Set elementFromNoDuplicateList : noDuplicates) {
if (equals(elementFromNoDuplicateList, possibleDuplicate)) {
alreadyInNoDuplicatesList = true;
break;
}
}
if (!alreadyInNoDuplicatesList) {
noDuplicates.add(possibleDuplicate);
}
}
return noDuplicates;
}

Put the Sets in a Set and they'll be removed as if by magic!

Related

how can i print custom class Duplicate if i am adding that object in list?

How can i print the duplicate of custom class object if i am adding that object inside list.
class Bank{
int id;
String name;
public Bank(int id,String name){
this.id=id;
this.name=name;
}
#Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
}
#Override
public String toString() {
return id+"\t"+name;
}
}
public class Service {
public static void main(String[] args) {
List<Bank> al=new ArrayList<Bank>();
Bank a=new Bank(11,"employee");
Bank b=new Bank(11,"employee");
Bank c=new Bank(12,"Bank");
Bank d=new Bank(12,"Bank");
al.add(a);
al.add(b);
al.add(c);
al.add(d);
}}
Here four bank object i am adding inside list. But a,b pointing to same object and similarly c and d pointing to same object How can i pointing to duplicate from above List.
You have 2 options to achieve this...
1st one is out of the box:
you need to use a Set, this collection doesnt allow duplicates, but you has no insertion order
2nd option.
you can write a method that is checking in the list is the element you are trying to insert is already there... list.contains(bank); where bank is the mthod to check...
in both cases is necessary to override the methods hashcode and equals(you already have this) in the class bank.
Example:
static List<Bank> al;
public static void main(String[] args) {
al = new ArrayList<Bank>();
Bank a = new Bank(11, "employee");
Bank b = new Bank(11, "employee");
Bank c = new Bank(12, "Bank");
Bank d = new Bank(12, "Bank");
addIfNotinList(a);
addIfNotinList(b);
addIfNotinList(c);
addIfNotinList(d);
System.out.println(al);
}
private static void addIfNotinList(Bank bank) {
if (!al.contains(bank)) {
al.add(bank);
}
}
and the Bank class
public class Bank {
int id;
String name;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Bank other = (Bank) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Bank(int id, String name) {
this.id = id;
this.name = name;
}
#Override
public String toString() {
return "Bank [id=" + id + ", name=" + name + "]";
}
}
Implement equals according to:
public boolean equals( Object obj ){
if ( this == obj ) return true;
if ( !(obj instanceof Bank) ) return false;
Bank other = (Bank)obj;
return this.id == other.id && this.name == other.name;
}
Perhaps comparing the id alone would be sufficient to establish equality.
Now you can do:
List<Bank> al=new ArrayList<Bank>();
Bank a=new Bank(11,"employee");
al.add( a );
Bank b=new Bank(11,"employee");
if( al.contains( b ) ){
// duplicate
} else {
al.add( b );
}

Check ArrayList for duplicates

Class:
public class Variant
{
private String variant;
private String quantity;
//getters and setters
}
ArrayList:
ArrayList<Variant> variantList = getVariantsList();
Now I want to check whether variantList contains a duplicate entry of variant or not? Please note that variant having two entries with different quantity are to be considered as duplicates.
You can simply ovveride your equals method in your Variant class and provide all the rules for equality in that method.
#Override
public boolean equals(Object obj) {
..
Then you can use contains method or just pass it to a Set, that eliminates all your duplicates.
If you want variant having two entries with different quantity also considered as dup, then you can add that condition in your equals.
Override equals(Object obj) method and try to compare the object on variant and quantity.
Try to loop thru the variantList and do check for duplicity using variantList.contains(variant).
There are two things you need to do:
Override the equals() in your Variant class(minimal code below):
Please note that the below code only checks for quantity and not the variant prop. Your IDE might help you to generate the equals() as well.
#Override
public boolean equals(Object object) {
boolean isEqual = (this == object);
if(object instanceof Variant){
Variant variant = (Variant) object;
isEqual = this.quantity.equals(variant.quantity);
}else{
isEqual = false;
}
return isEqual;
}
Check if the List contains the object - which will use the equals() to check if both are equal.
for (Variant variant : variantList) {
if (variantList.contains(variant)) {
//do logic if its present
}
}
Just check one object with other objects of list
Override equals method in Variant class
#Override
public boolean equals(Object obj) {
if (obj != null) {
if (obj instanceof Variant) {
Variant temp = (Variant) obj;
return this.quantity.equals(temp.quantity); //for different quantity
} else {
return false;
}
}
return false;
}
Then check :
for (int i = 0; i < variantList.size(); i++) {
for (int j = 0; j < variantList.size(); j++) {
if (i != j) {
if (iList.get(i).equals(iList.get(j))) {
//logic when duplicate
break;
}
}
}
}
Follow the below guidelines:
Your Class Variant must override the equals method, since you define a duplicate condition based on quality hence in the equals method check for quality attribute value i.e.
public class Variant {
private String variant;
private String quantity;
public Variant(String variant, String quantity) {
this.variant = variant;
this.quantity = quantity;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((quantity == null) ? 0 : quantity.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Variant other = (Variant) obj;
if (quantity == null) {
if (other.quantity != null)
return false;
} else if (!quantity.equals(other.quantity))
return false;
return true;
}
}
Create a method which basically checking whether your list contains the duplicate entries(Variant) or not and return true and false accordingly:
private static boolean isListContainsDuplicateEntries(
ArrayList variantList) {
final List setToReturn = new ArrayList();
for (Variant v : variantList) {
if (!setToReturn.contains(v)) {
setToReturn.add(v);
} else {
return true;
}
}
return false;
}
Now, test the functionality:
public static void main(String[] args) {
Variant variant1 = new Variant("1", "100");
Variant variant2 = new Variant("2", "200");
Variant variant3 = new Variant("3", "200");
ArrayList<Variant> variantList = new ArrayList<>();
variantList.add(variant1);
variantList.add(variant2);
variantList.add(variant3);
System.out.println(Variant.isListContainsDuplicateEntries(variantList));
Output: true
You can use contains():
if (variantList.contains(**<some other Variant object>**)){
...
}
You can simply override your equals method in your Variant and try like this
List<Varient> list =getVariantsList();
System.out.println("here list size"+list.size());
Set<Varient> set = new HashSet<Varient>(list);
System.out.println("here"+set.size());
Create a varient Object:
public class Varient {
private String variant;
private String quantity;
public String getVariant() {
return variant;
}
public void setVariant(String variant) {
this.variant = variant;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Varient)) return false;
Varient varient = (Varient) o;
if (!quantity.equals(varient.quantity)) return false;
if (!variant.equals(varient.variant)) return false;
return true;
}
#Override
public int hashCode() {
int result = variant.hashCode();
result = 31 * result + quantity.hashCode();
return result;
}
}
Here is your main Program;
public class Test {
public static void main (String [] args){
// getVariantsList() here your list
List<Varient> list =getVariantsList();
Set<Varient> set = new LinkedHashSet<Varient>(list);
}
}
public class Variant {
private String variant;
private String quantity;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((variant == null) ? 0 : variant.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Variant other = (Variant) obj;
if (variant == null) {
if (other.variant != null)
return false;
} else if (!variant.equals(other.variant))
return false;
return true;
}
public String getVariant() {
return variant;
}
public void setVariant(String variant) {
this.variant = variant;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
public static void main(String[] args) {
// HashSet<Variant> set = new HashSet<>();
// LinkedHashSet<Variant> linkedSet = new LinkedHashSet<>(); // stores
// in input order
/*
* You can use treeset to store data in custom order, in this case
* lexicographically
*/
TreeSet<Variant> treeSet = new TreeSet<>(new VariantComparator());
}
}

Compare List value of different types

I am trying to compare a list of type Car that has no equals method.
Car.java
public class Car {
private int carNumber;
private String carName;
public Car(int carNumber, String carName)
{
super();
this.carNumber = carNumber;
this.carName = carName;
}
/**
* #return The carNumber.
*/
public int getCarNumber()
{
return carNumber;
}
/**
* #param carNumber The carNumber to set.
*/
public void setCarNumber(int carNumber)
{
this.carNumber = carNumber;
}
/**
* #return The carName.
*/
public String getCarName()
{
return carName;
}
/**
* #param carName The carName to set.
*/
public void setCarName(String carName)
{
this.carName = carName;
} }
Main class :
import java.util.ArrayList;
import java.util.List;
public class ListCar
{
public static void main (String[] args)
{
Car carList1_a = new Car(1, "Camry");
Car carList1_b = new Car(2, "Corolla");
Car carList1_d = new Car(3, "BMW");
Car carList2_d = new Car(3, "BMW");
Car carList2_a = new Car(2, "Corolla");
Car carList2_b = new Car(1, "Camry");
List<Car> carList1 = new ArrayList<Car>();
carList1.add(carList1_a);
carList1.add(carList1_b);
carList1.add(carList1_d);
List<Car> carList2 = new ArrayList<Car>();
carList2.add(carList2_b);
carList2.add(carList2_d);
carList2.add(carList2_a);
System.out.println(compareLists(carList1, carList2));
}
public static boolean compareLists(List<Car> prevList, List<Car> modelList)
{
if (prevList!= null && modelList!=null && prevList.size() == modelList.size())
{
boolean indicator = false;
for (Car modelListdata : modelList)
{
for (Car prevListdata : prevList)
{
if (prevListdata.getCarName().equals(modelListdata.getCarName()) && prevListdata.getCarNumber() == modelListdata.getCarNumber())
{
return true;
}
if (modelListdata.getCarName().equals(prevListdata.getCarName()))
{
indicator = false;
break;
}
else
{
indicator = true;
}
}
}
if (indicator)
{
return true;
}
}
return false;
}
}
The above method compareLists() does not compare the entire list , I am looking to improvise the method to compare each element of the list of Car type regardless of the order. Without equals method in the Car class.
Any input would be helpful
Thanks !!!
You need to iterate the first List and check that every element is in the second list. If you found an element not found in the second list, the lists are different.
The implementation could be:
public static boolean compareLists(List<Car> prevList, List<Car> modelList)
{
boolean listEquals = true;
if (prevList!= null && modelList!=null && prevList.size() == modelList.size())
{
for (Car modelListdata : modelList)
{
boolean elementInList = false;
for (Car prevListdata : prevList)
{
if (prevListdata.getCarName().equals(modelListdata.getCarName()) && prevListdata.getCarNumber() == modelListdata.getCarNumber())
{
/* The list has the element, set the flag to true and break the loop */
elementInList = true;
break;
}
}
if (elementInList == false) {
/* There is one element not found in the second list, the lists are not equals */
listEquals = false;
break;
}
}
return listEquals;
} else {
/* At least one list is null or the size is not the same */
return false;
}
}
If you implement the equals() and hashCode() methods in your Car class, the code is much more simple as you could use the contains() method of the list:
public static boolean compareListsEquals(List<Car> prevList, List<Car> modelList)
{
if (prevList!= null && modelList!=null && prevList.size() == modelList.size())
{
for (Car modelListdata : modelList)
{
if (prevList.contains(modelListdata) == false) {
return false;
}
}
return true;
} else {
/* At least one list is null or the size is not the same */
return false;
}
}
If you want to see if lists are equal without using equal method for car, then you should:
1. Stop using iterators.
You should be comparing first element with first element. Second with second etc.
You need to use element at the same position in both lists.
It will work given that if lists have different number of elements - it will not be equal.
Using iterators is problematic for that.
2. Check only for not equal elements - in that case return false.
3. At the end of algorithm return true - when each element was checked and passed.
4. Be sure you correctly handles cases with different sizes of list (return false) or when one of them is null (return false) or when both are null (return true).
I hope that helps. Let me know if you need more detailed version with some example.
Check if that return true is a smart thing to do.
[EDIT]
Ok, since it smells like homework I just wanted to give a hint... but here it comes the spoon.
The answer from David is pretty good so I won't reiterate the answer. No pun intended.

Method that adds elements to set always throwing custom exception

Ok, so I've got a method which adds elements to a list but it is always throwing my custom exception, no matter what, even when there are no elements in the Set I made.
private Set<Plan> planSet = new HashSet<Plan>();
public Plan createPlan(String name) throws DuplicatePlan{
Plan plan = new Plan(name);
if(!planSet.contains(plan)){
planSet.add(plan);
} else {
throw(new DuplicatePlan("Error, duplicate plan"));
}
return plan;
}
I'm thinking that my equals() and hashCode() methods are causing this. Currently I'm using the default overridden Eclipse hashCode() and equals(), this is what I've got there:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj){
return true;
} if (obj == null){
return false;
} if (getClass() != obj.getClass()){
return false;
}
Plan other = (Plan) obj;
if (name == null) {
if (other.name != null){
return false;
}
} else if (!name.equals(other.name)){
return false;
}
return true;
}
This is what Plan does:
private String name;
private Set<Tables> tablesSet;
public Plan(String name){
this.name = name ;
}
Here's what's supposed to happen if a user sets the same name in the TextField:
newPlan.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent action){
if(!newPlan.getText().isEmpty()){
try {
String name = planName.getText();
plan.createPLan(name);
esquema = esquemas.createPlan(planName.getText());
optionsPlans.getItems().add(plan.getName());
} catch (DuplicatePlan e) {
dialog.errorDialog(planError, duplicate);
}
} else {
dialog.errorDialog(empty, emptySpace);
}
}
});
Had to use Answer because it was too long for comment.
This here looks suspicious to me:
String name = planName.getText();
plan.createPLan(name);
esquema = esquemas.createPlan(planName.getText());
I.e. what's up with createPLan and createPlan? Copy & paste error? Or are you calling the same method twice (which would explain the behavior)?

Remove Duplicates from ArrayList filled with POJOs

I have an ArrayList filled POJOs and I want to remove all POJOs, which have a duplicate variable. This is the POJO:
public static class UrlStore {
public String url;
public String data;
public UrlStore(String url) {
this.url = url;
}
public void setData(String data) {
this.data = data;
}
}
My way to remove duplicate "url"-variables in the ArrayList<UrlStore> is to iterate through the list and to remove those duplicates. It was said to me that I could simply use a Set to do this, but I can't figure out how to use it with an ArrayList containing POJOs. Or do you have even a better way?
Thanks for any suggestions!
You can override the equals() and hashCode() methods in your POJO and pass the List<UrlStore> to the Set.
List<UrlStore> listOfUrlStore = ......
Set<UrlStore> foo = new HashSet<UrlStore>(listOfUrlStore);
I have used a simple HashSet here , the correct implementation of Set depends on your requirement. You can even convert the Set back to the List .
listOfUrlStore.clear();
listOfUrlStore.addAll(foo);
package test.urlstore;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class DuplicateDemo{
public static void main(String[] args) throws Exception {
List<UrlStore> urlStores = new ArrayList<UrlStore>();
UrlStore usg = new UrlStore("google");
UrlStore usy = new UrlStore("yahoo");
UrlStore usb = new UrlStore("bing");
UrlStore usa = new UrlStore("ask");
UrlStore usd = new UrlStore("duckduckgo");
usg.setData("mail");
urlStores.add(usg);
usg = new UrlStore("google");
usg.setData("search");
urlStores.add(usg);
usg = new UrlStore("google");
usg.setData("doc");
urlStores.add(usg);
usg = new UrlStore("google");
usg.setData("search");
urlStores.add(usg);
usg = new UrlStore("google");
usy.setData("search");
urlStores.add(usy);
usy.setData("search");
urlStores.add(usy);
usb.setData("search");
urlStores.add(usb);
usb.setData("search");
urlStores.add(usb);
usa.setData("search");
urlStores.add(usa);
usd.setData("search");
urlStores.add(usd);
System.out.println("before removing duplicates");
// before removing duplicates
for (Iterator iterator = urlStores.iterator(); iterator.hasNext();) {
UrlStore urlStore = (UrlStore) iterator.next();
System.out.println(urlStore.toString());
}
System.out.println("\n\nafter removing duplicates");
//removing duplicates
Set<UrlStore> uniqueUrlStores = new HashSet<UrlStore>(urlStores);
//After removing duplicates
for (Iterator iterator = uniqueUrlStores.iterator(); iterator.hasNext();) {
UrlStore urlStore = (UrlStore) iterator.next();
System.out.println(urlStore.toString());
}
}
static class UrlStore {
public String url;
public String data;
public UrlStore(String url) {
this.url = url;
}
public void setData(String data) {
this.data = data;
}
#Override
public String toString() {
return "UrlStore [url=" + url + ", data=" + data + "]";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UrlStore other = (UrlStore) obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
if (url == null) {
if (other.url != null)
return false;
} else if (!url.equals(other.url))
return false;
return true;
}
}
}
Override hashCode() and equals() in your POJO and then:
List<URLStore>() list = //Your list;
Set<URLStore> set =new HashSet<URLStore>(list);
Don't forget to override the equals method of your POJO.
One this is done, you could use contains method of List to check if your object is in the list before add it.
For the Set, you don't have to use it with the list, it replace the list. You can populate a Set from a List with addAll(Collection c)

Categories

Resources