Using contains method to avoid duplicates - java

I am creating a List that converts a List of Observations(Registration registration, Time time) into a List containing only Registrations, however this list cannot contain duplicates and I'm battling to ensure that duplicates don't occur.
public List<Registration> getVehicles(){
List<Registration> rtnList = new ArrayList<Registration>();
for (Observation obs:observationsList){
if (rtnList.contains(obs.getIdentifier())){
}
else
rtnList.add(obs.getIdentifier());
}
return rtnList;
}
This is what I have got, but duplicates still occur.
With observations such as the following:
obsList.record (new Registration("CA 976-543"), new Time("13:15:03"));
obsList.record (new Registration("BCD 123 MP"), new Time("13:21:47"));
obsList.record (new Registration("CA 976-543"), new Time("13:35:50"));
The .equals() method for the Registration class is:
public boolean equals(Registration other){
if (getIdentifier().equals(other.getIdentifier()))
return true;
return false;
}
I would like the output of obsList.getVehicles to be :
[CA 976-543, BCD 123 MP]
But instead I am getting:
[CA 976-543, BCD 123 MP, CA 976-543]

The contains method uses the elements' equals method. For lists, it essentially iterates over all the elements of the list and checks if that element is equal to the value passed.
According to your last comment, you haven't properly overridden it. equals takes an Obejct argument. In fact, instead of overriding the method, you've overloaded it. Using the #Override annotation would have, in fact, caused a compilation error on this method and made the mistake clearer:
#Override
public boolean equals(Object o) { // Note the argument type
if (!(o instanceof Registration)) {
return false;
}
Registration other = (Registration) o;
return getIdentifier().equals(other.getIdentifier()) &&
getProvince().equals(other.getProvince());
}

Related

How to add elements to an object list in java

public class Bus{
private int seats;
private List<People> currentPeople;
public Bus(int seats){
this.seats = seats;
}
public void passengers(List<People> boarders, List<People> deboarders){
this.currentPeople.remove(deboarders);
this.currentPeople.add(boarders);
}
I'm trying to create a list of people on the bus. I'm trying to remove deboarders(alighting passengers) from the list and add the boarders(boarding passengers). But Java won't let me add the boarders to the currentPeople list. People is a class which stores the name and ticket number of the passanger. Any help on this? I've been trying to solve this for hours.
To add a collection of objects to a list you need to use addAll:
this.currentPeople.addAll(boarders);
To remove a collection of objects from a list you need to use removeAll:
this.currentPeople.removeAll(deboarders);
Be careful, in order to compare and remove the right elements from the list, removeAll uses equals method. So you should implement equals method in your People class.
EDIT:
equals method for People class:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
People people = (People) o;
if (ticketNumber != people.ticketNumber) return false;
return name != null ? name.equals(people.name) : people.name == null;
}
Don't forget to initialize currentPeople list, otherwise you will get NullPointerException.
Try removeAll() and addAll() methods because you are passing a Collection as a parameter.
Do not forget " ; " at the end of the line inside your constructor.
this.currentPeople.removeAll(deboarders);
this.currentPeople.addAll(boarders);
Change add to addAll and likewise for remove.
As Federico points out in comments, assuming People has equals method implemented.

Removing specific element from ArrayList

I need help with removing just added element from the arrayList.
I have a private static ArrayList<Position> positions = new ArrayList<>() to which I'm adding objects of the class Position with parameters name, quantity, and price.
Than I have a method adding objects to the list, and in case if the same product is added for the second time, it is supposed to add the quantity to the first object of that name and remove that second one.
So far I have this method:
public void addPosition(Position p) {
for (Position poz: positions) {
if (poz.getname().equals(p.getname())) {
poz.setquantity(poz.getquantity() + p.getquantity());
}
} positions.add(p);
}
Adding quantities works just fine, but I've got problem with removing the element with recurring name.
Please help.
You shouldn't add duplicate items and then remove them. Just declare a method which handles adding items correctly; that is, it adds the item if it does not exist, and it updates the quantity if it does exist.
It should look like this:
public void addPosition(Position addition) {
//flag to track whether the new item exists in the list
boolean itemExists = false;
//go through the list looking for an item with the passed name to update
for (Position existing : positions) {
if (existing.getName().equals(addition.getName())) {
existing.setQuantity(existing.getQuantity() + addition.getQuantity());
itemExists = true;
}
}
//if no matching item was found, add the new item
if (!itemExists) {
positions.add(addition);
}
}
The above should work. If you care about performance, it might be better to use a HashMap so you can look up the Position by name instead of looping through the whole list each time.
If you are interested to know other data Structure , i want suggest you HashSet , by default it will not insert duplicates for primitive objects .
In your case the only thing you need to do to your Position class , is to add
equals and hashCode methods . As getters and setters Eclipse for example will create by him self .
hashCode()
As you know this method provides the has code of an object. Basically the default implementation of hashCode() provided by Object is derived by mapping the memory address to an integer value. If look into the source of Object class , you will find the following code for the hashCode. public native int hashCode(); It indicates that hashCode is the native implementation which provides the memory address to a certain extent. However it is possible to override the hashCode method in your implementation class.
equals()
This particular method is used to make equal comparison between two objects. There are two types of comparisons in Java. One is using “= =” operator and another is “equals()”. I hope that you know the difference between this two. More specifically the “.equals()” refers to equivalence relations. So in broad sense you say that two objects are equivalent they satisfy the “equals()” condition. If you look into the source code of Object class you will find the following code for the equals() method.
Here a complete working example ( you can modify your class following this cose)
import java.util.HashSet;
public class Zhashset{
private int num;
public Zhashset(){
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + num;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Zhashset other = (Zhashset) obj;
if (num != other.num)
return false;
return true;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HashSet<Zhashset> hs = new HashSet<Zhashset>();
hs.add(new Zhashset());
hs.add(new Zhashset());
for(Zhashset item : hs)
System.out.println(item.getNum());
}
}
Output will be : 0 written only once.

Object as a key in treemap in java 8

CompareObj is a class in java It consists of three attributes String rowKey, Integer hitCount, Long recency
public CompareObj(String string, Integer i) {
this.rowKey = string;
this.hitCount = i%10;
this.recency= (Long) i*1000;
}
Now I created a treeMap
Comparator<CompareObj> comp1 = (e1,e2) -> e1.getHitCount().compareTo(e2.getHitCount());
Comparator<CompareObj> comp2 = (e1,e2) -> e2.getRecency().compareTo(e1.getRecency());
Comparator<CompareObj> result = comp1.thenComparing(comp2);
TreeMap<CompareObj, CompareObj> tM = new TreeMap<CompareObj, CompareObj>(result);
for(int i=0;i<=1000;i++)
{
CompareObj cO = new CompareObj("A"+i, i);
tM.put(cO,cO);
}
for(int i=0;i<=1000;i++)
{
CompareObj cO = new CompareObj("A"+i, i);
CompareObj values = tM.get(cO);
System.out.println(values.getRowKey()); // Line 28: get Null Pointer Exception
}
Also I overide hashCode and Equals. Still I get nullponter exception.
#Override
public int hashCode() {
return Objects.hash(getRowKey());
}
#Override
public boolean equals(Object obj) {
if(this==obj) return true;
if(!(obj instanceof CompareObj)) return false;
CompareObj compareObj = (CompareObj) obj;
return Objects.equals(this.getRowKey(), compareObj.getRowKey());
}
Here when I try to retrive value from treemap back I get Null Pointer exception in the line mentioned. How to solve this
If I want to implement comapareTo() of Comaprable interface, how should I implement if there is multiple sort conditions.
The first thing to understand, is the NullPointerException. If you get that exception on the exact line
System.out.println(values.getRowKey());
then either System.out or values is null. Since we can preclude System.out being null, it’s the values variable, which contains the result of get and can be null if the lookup failed.
Since you are initializing the TreeMap with a custom Comparator, that Comparatordetermines equality. Your Comparator is based on the properties getHitCount() and getRecency() which must match, which implies that when the lookup fails, the map doesn’t contain an object having the same values as reported by these two methods.
You show that you construct objects with the same values but not the code of these getters. There must be an inconsistency. As Misha pointed out, your posted code can’t be the code you have ran when getting the exception, therefore we can’t help you further (unless you post the real code you ran).

I have two arrayList<myObject>, I'm not able to use equals() to be able to compare them correctly. Why?

I have two arrayLists<myObject>, where myObject is an object of a custom class I've created. I want to be able to compare those arrayLists using the equals() method.
After reading and looking for answers, I've read that certain objects like int[] are only considered equal by the equals() method when they are referencing the same thing.
To fix that, I tried to override the equals method in my custom object. My objects have 3 atributes (all basic types), so my equals method now returns true if all the 3 atributes are equal to those of the object compared, and false otherwise. However, comparing the arraylists still doesn't work. What am I doing wrong?
Excuse me for explaining the code instead of posting it, I do it because the variables and names aren't in English.
EDIT: Ok, here's the code. Compra is my custom class; cantidad,concepto and id are its atributes.
#Override
public boolean equals(Object obj) {
boolean result = true;
if (obj == null) {
result = false;
}else{
Compra comprobada = (Compra) obj;
if(!(this.id == comprobada.getId())){
result = false;
}
if(!(this.cantidad == comprobada.getCantidad())){
result = false;
} if(!this.concepto.equals(comprobada.getConcepto())){
result = false;
}
}
return result;
}
Based on this one :
How can I check if two ArrayList differ, I don't care what's changed
If you have implemented your custom object equals correct (you actually override it and have your one) and the size of the arrayList is the same and each of the pair of the objects is equal then it will return equal. In other words what you are trying to do is totally correct but your arrayLists are not actually having exactly the equal objects in exact order.
Make sure that your equal is called when you check for collection equality by doing a System.out.println() to investigate what is going on.
If you don't mind please send the equals of your object.
I run your code in an isolated example and works fine (outtputs true) - I improved the equals method so it doesn't do so many if checks as if only one of them is not equal it should return false.
class stackoverflow {
public static void main(String args[]){
ArrayList<Compra> array1 = new ArrayList<>();
ArrayList<Compra> array2 = new ArrayList<>();
array1.add(new Compra(1,2,"test"));
array2.add(new Compra(1,2,"test"));
System.out.println(array1.equals(array2));
}
}
class Compra {
int id;
int cantidad;
String concepto;
public Compra(int id, int cantidad, String concepto){
this.id = id;
this.cantidad = cantidad;
this.concepto = concepto;
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}else{
Compra comprobada = (Compra) obj;
if(!(this.id == comprobada.getId())){
return false;
}
if(!(this.cantidad == comprobada.getCantidad())){
return false;
}
if(!this.concepto.equals(comprobada.getConcepto())){
return false;
}
}
return true;
}
public int getId() {
return id;
}
public int getCantidad() {
return cantidad;
}
public String getConcepto() {
return concepto;
}
}
Some things to check:
Are you sure you don't change the order of the things in ArrayList??:
Do you print to make sure that these equals checks happen and return true or false as expected?
Are you sure that concepto Strings are exactly the same, with the same case and don't contain extra spaces etc?
As you haven't posted code i suggest you to check into Comparable class and method compareTo and how to use it for custom classes.

getting an object from an arrayList with objects attribute

I have 2 classes.
public class klass1 {
String bir;
String myID;
klass1(String bir, String myID)
{
this.bir=bir;
this.myID=myID;
}
}
.
import java.util.*;
public class dd {
public static void main(String[] args) {
ArrayList<Object> ar=new ArrayList();
ar.add(new klass1("wer","32"));
ar.add(new klass1("das","23"));
ar.add(new klass1("vz","45"));
ar.add(new klass1("yte","12"));
ar.add(new klass1("rwwer","43"));
ar.remove(new klass1("vz","45"));//it's not worked!!!
System.out.println(ar.size());
}
}
What I want is removing or getting an object from array list with object's second attribute. How can I do that? Is there an easy way for it?
Just implement the equals method in the class Klass1.
public class Klass1 {
String bir;
String myID;
Klass1(String bir, String myID)
{
this.bir=bir;
this.myID=myID;
}
public boolean equals(Object o){
if(o instanceof Klass1)
return ((Klass1)o).myID.equals(myID);
else
return false;
}
}
Its because you are trying to delete a new object which isnt in the arraylist. When you use new klass1("vz","45") you are creating a new instance of this class which isnt in the arraylist.
What the system does internally is to compare those classes using equals. Why this doesn't work is explained in the following code:
Object o1 = new Object();
Object o2 = new Object();
System.out.println(o1 == o2); // false, obviously
System.out.println(o1.equals(o2)); // false
System.out.println(o1); // java.lang.Object#17046822
System.out.println(o2); // java.lang.Object#22509bfc
You can tell by the number following the # that these objects have a different hash values, and this is what the equals function of Object does check.
This is relevant for your klass, because unless you overwrite equals, you will use the equals of Object. And if you implement equals you should always implement hashcode as well. Because both tell you something about whether or not two objects are the "same", and if the one says something else than the other, some part of your code might get confused.
How to properly implement equals for your class:
#Override
public int hashCode() {
int hash = 7;
hash = 17 * hash + Objects.hashCode(this.bir);
hash = 17 * hash + Objects.hashCode(this.myID);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final klass1 other = (klass1) obj;
if (!Objects.equals(this.bir, other.bir)) {
return false;
}
if (!Objects.equals(this.myID, other.myID)) {
return false;
}
return true;
}
This can be done in most IDEs btw with a shortcut (i.E. alt-insert in Netbeans). Note that I did this in Java 7 using Objects. If you are in Java 6, you need to manually type(a == b) || (a != null && a.equals(b)); with the appropriate objects to compare.
Creating a proper hashcode is not always trivial, for more complex objects you might want to read a bit about hashcodes first. For simple objects: multiply primes with something.
The equals method is usually trivial, it is just important to first check for null and for class equality. This is often forgotten by programmers and a common source for NullPointerExceptions and ClassCastExceptions.

Categories