Java ArrayList removeAll - java

I am working on a dummy hospital database. I have an ArrayList that has the combination of all possible times that a doctor can theoretically hold an appointment, and another ArrayList that holds actual registered appointments.
Availability {
int doctorid;
String specialty;
Date date;
int order_of_appointment;
}
//////////
ArrayList<Availability> allTimes;
ArrayList<Availability> busyTimes;
What I want to accomplish is finding the times where doctors are free. Which is the result of (allTimes - busyTimes)
I tried using allTimes.removeAll(busyTimes) but it didn't remove anything.
I made sure that I am overriding the equals() method in the Availability class but it still doesn't remove anything.
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Availability)) return false;
Availability that = (Availability) o;
return doctorid == that.doctorid &&
order_of_appointment == that.order_of_appointment &&
Objects.equals(specialty, that.specialty) &&
Objects.equals(date, that.date);
}
Output:
busyTimes =
[Availability{doctorid=1, specialty='internal medicine', date=2021-11-02, order_of_appointment=2}
]
allTimes =
[Availability{doctorid=1, specialty='internal medicine', date=2021-11-02, order_of_appointment=1}
, Availability{doctorid=1, specialty='internal medicine', date=2021-11-02, order_of_appointment=2}
, Availability{doctorid=1, specialty='internal medicine', date=2021-11-02, order_of_appointment=3}]
The output I get for freeTimes is identical to allTimes even though I'm expecting it to remove the appointment with order_of_appointment==2.
I am totally clueless on what might be causing this. Any help would be appreciated. Thanks in advance!

You don't show how are you creating the array, or how are you adding the elements.
I did a simple program with ArrayLists and works as expected:
import java.util.*;
class A {
int id;
A(int id) {
this.id = id;
}
#Override
public boolean equals(Object o) {
return o instanceof A && this.id == ((A)o).id;
}
public String toString() {
return String.format("A{id:%s}", id);
}
public static void main(String ... args) {
List<A> a = new ArrayList<A>(Arrays.asList(new A(1), new A(2)));
List<A> b = new ArrayList<A>(Arrays.asList(new A(2), new A(3)));
a.removeAll(b);
System.out.println(a);
}
}
Output:
[A{id:1}]

What was wrong is that even though I had the date format set up as "yyyy-MM-dd", it still stored the time inside the Date object. I converted the Date objects to strings and then compared the strings and that worked. Thank you all.

You need to override equals(Object obj) method in Availability class with your comparison logic.
I implemented it. please check.
import java.util.Date;
public class Availability {
private int doctorId;
private String specialty;
private Date date;
private int orderOfAppointment;
public Availability() {
super();
}
public Availability(int doctorId, String specialty, Date date, int orderOfAppointment) {
super();
this.doctorId = doctorId;
this.specialty = specialty;
this.date = date;
this.orderOfAppointment = orderOfAppointment;
}
public int getDoctorId() {
return doctorId;
}
public void setDoctorId(int doctorId) {
this.doctorId = doctorId;
}
public String getSpecialty() {
return specialty;
}
public void setSpecialty(String specialty) {
this.specialty = specialty;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getOrderOfAppointment() {
return orderOfAppointment;
}
public void setOrderOfAppointment(int orderOfAppointment) {
this.orderOfAppointment = orderOfAppointment;
}
#Override
public String toString() {
return "Availability [doctorId=" + doctorId + ", specialty=" + specialty + ", date=" + date
+ ", orderOfAppointment=" + orderOfAppointment + "]";
}
#Override
public boolean equals(Object obj) {
boolean returnVal = false;
Availability busyslote = (Availability) obj;
if (this.doctorId == busyslote.doctorId && this.orderOfAppointment == busyslote.orderOfAppointment
&& this.specialty.equalsIgnoreCase(busyslote.specialty) && this.date.equals(busyslote.date)) {
returnVal = true;
} else {
returnVal = false;
}
return returnVal;
}
}
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class AppointmentMain {
public static void main(String[] args) {
List<Availability> allAppointment = new ArrayList<>();
List<Availability> attenedAppointment = new ArrayList<>();
Availability obj1 = new Availability(1, "Internal Medicine", new Date(), 1);
Availability obj2 = new Availability(1, "Internal Medicine", new Date(), 2);
Availability obj3 = new Availability(1, "Internal Medicine", new Date(), 3);
allAppointment.add(obj1);
allAppointment.add(obj2);
allAppointment.add(obj3);
Availability obj4 = new Availability(1, "Internal Medicine", new Date(), 3);
attenedAppointment.add(obj4);
System.out.println("Befour count :" + allAppointment.size());
allAppointment.removeAll(attenedAppointment);
System.out.println("After count :" + allAppointment.size());
}
}

Related

Count occurrence HashMap

I'm trying to count the number of diseases a day by using hashmap:
public static main(String[] args){
Disease cholera=new Disease("cholera");
Disease dengue=new Disease("dengue");
List<Diagnosis> diagnoses = Arrays.asList(
new Diagnosis(cholera, 0), // registered cholera on day 0
new Diagnosis(cholera, 0),
new Diagnosis(cholera, 1),
new Diagnosis(cholera, 1),
new Diagnosis(cholera, 2),
new Diagnosis(cholera, 2)
);
printFreq(diagnosis);
}
public static void printFreq(List<Diagnosis> diagnoses) {
Map<Diagnosis, Integer> hm = new HashMap();
for (Diagnosis x : diagnoses) {
if (!hm.containsKey(x)) {
hm.put(x, 1);
} else {
hm.put(x, hm.get(x) + 1);
}
}
But if I call printFreq(diagnoses) I get:{{cholera, 0}=1, {cholera, 1}=1, {cholera, 2}=1, {cholera, 0}=1, {dengue, 0}=1, {cholera, 1}=1, {cholera, 2}=1}. How can I fix this to {{cholera,0}=2,{dengue0}=1,{cholera,1}=2,{cholera,2}=2}}
I'm not allowed to change the Diagnosis or Disease class but this is how they look like:
public class Disease {
private final String name;
public Disease(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Disease disease = (Disease) o;
return name.equals(disease.name);
}
#Override
public int hashCode() {
return name.hashCode();
}
#Override
public String toString() {
return name;
}
Diagnosis:
public class Diagnosis {
private final Disease disease;
private final int day;
public Diagnosis(Disease disease, int day) {
this.disease = disease;
this.day = day;
}
public Disease getDisease() {
return disease;
}
public int getDay() {
return day;
}
#Override
public String toString() {
return "{" + disease + ", " + day + "}";
}
You can add a wrapper class to make life easier. In this code I have a wrapper class DiagnosisMetric that wraps the Diagnosis class.
Following is the new implementation of the printFreq function.
public static void printFreq(List<Diagnosis> diagnoses) {
Map<DiagnosisMetric, Long> collect = diagnoses.stream().
collect(Collectors.groupingBy(DiagnosisMetric::new, counting()));
System.out.println(collect);
}
And, following is the wrapper class. Notice that I have implemented equals and hashCode as per the requirement.
public static class DiagnosisMetric {
private Diagnosis diagnosis;
public DiagnosisMetric(Diagnosis s) {
this.diagnosis = s;
}
public Diagnosis getDiagnosis() {
return diagnosis;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DiagnosisMetric that = (DiagnosisMetric) o;
return diagnosis.getDisease().getName().
equals(that.getDiagnosis().getDisease().getName())
&& diagnosis.getDay() == that.getDiagnosis().getDay();
}
#Override
public int hashCode() {
return Objects.hash(diagnosis.getDay(),
diagnosis.getDisease().getName());
}
#Override
public String toString() {
String disease = diagnosis.getDisease().getName();
int day = diagnosis.getDay();
return "{" + disease + ", " + day + "}";
}
}
An ad-hoc solution which does not require storing the intermediate map with Diagnosis key (which cannot be used as a map key without properly implemented hashCode and equals as mentioned earlier) is like this:
use a raw list containing diagnosis.day and disease.name as a key wrapper in Collectors.groupingBy
calculate the frequencies (e.g. using Collectors.summingInt)
use Supplier<Map> to provide a tree map sorted by the list contents
print the stats
diagnoses.stream()
.collect(Collectors.groupingBy(
d -> Arrays.asList(d.getDay(), d.getDisease().getName()),
() -> new TreeMap<List<?>, Integer> (Comparator
.comparingInt((List k) -> (Integer) k.get(0))
.thenComparing((List k) -> (String) k.get(1))
),
Collectors.summingInt(d -> 1)
)) // Map<List, Integer> created here
.forEach((k, v) -> System.out.println(k + " = " + v));
Output:
[0, cholera] = 2
[0, dengue] = 1
[1, cholera] = 2
[2, cholera] = 2
To resolve this what we need to do is to override the hashCode and equals method for the Diagnosis class, like this:
#Override
public boolean equals(Object obj) {
Diagnosis diagnosis = (Diagnosis) obj;
return this.day == diagnosis.day && this.disease == diagnosis.disease;
}
#Override
public int hashCode() {
char[] charArr = this.disease.toString().toCharArray();
int sum = 0;
for (int i = 0; i < charArr.length; i++) {
sum += charArr[i];
}
return sum;
}
Also you need to override equals method of the Disease class, here is code for that:
#Override
public boolean equals(Object obj) {
Disease disease = (Disease) obj;
return this.disease.equalsIgnoreCase(disease.toString());
}

Java 4 : Sorting an array by 2 values

I'm currently working on a project which is in Java 4 and I have to sort an ArrayList by 2 values. This is an ArrayList of ClassTest.
public class ClassTest{
String code; // "01", "02" or "03".
String date; // 01/01/2001.
}
My problem is that I have to sort in first by code and after by the closest date of the current date. I'm in Java 4 and I can't use many things I usually used for sorting an Array like Comparator<ClassTest>.
What algorithm can I use that isn't too slow?
Using Comparator interface, without Generics (<..>)
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
public class CollectionSorter {
public static void main(String args[]) {
ClassTest obj1 = new ClassTest();
obj1.setCode("01");
obj1.setDate("2001-02-01");
ClassTest obj2 = new ClassTest();
obj2.setCode("01");
obj2.setDate("2001-01-01");
ClassTest obj3 = new ClassTest();
obj3.setCode("02");
obj3.setDate("2001-01-01");
List list = new ArrayList();
list.add(obj1);
list.add(obj2);
list.add(obj3);
System.out.println("Before sorting - " + list);
Collections.sort(list, new ClassTestComparator());
System.out.println("After sorting - " + list);
}
}
class ClassTest{
private String code; // "01", "02" or "03".
private String date; // 01/01/2001.
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String toString()
{
return "[code: " + code + ", date: " + date + "]";
}
}
class ClassTestComparator implements Comparator {
public int compare(Object o1, Object o2) {
ClassTest obj1 = (ClassTest) o1;
ClassTest obj2 = (ClassTest) o2;
int code1 = Integer.parseInt(obj1.getCode());
int code2 = Integer.parseInt(obj2.getCode());
int result = 0;
if(code1 > code2) {
result = 1;
}
if(code1 < code2) {
result = -1;
}
if (result != 0) {
return result;
}
// Sort by Date ("by the closest date of the current date")
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = null;
Date date2 = null;
try {
date1 = sdf.parse(obj1.getDate());
date2 = sdf.parse(obj2.getDate());
} catch(ParseException e) {
e.printStackTrace();
}
if(date1.compareTo(date2)>0){
result = 1;
}else if(date1.compareTo(date2)<0){
result = -1;
}else if(date1.compareTo(date2)==0){
result = 0;
}
return result;
}
}
Note: The code is tested in Java 1.4 version and works as expected
I don't know if this is possible in your Java-Version, but maybe you can try this way:
public class ClassTest implements Comparable<ClassTest> {
String code; // "01", "02" or "03".
String date; // 01/01/2001.
#Override
public int compareTo(ClassTest ct) {
// Sort by Code
result = code.compateTo(ct.code);
if (result != 0){return result;}
// Sort by Date ("by the closest date of the current date")
result = (...)
return result;
}
}
And then you can just call
Collections.sort(yourArrayListOfClassTest);

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 );
}

What is the correct way to do this?

I know this must be a fundamental design problem because I clearly can't do this. I want to call the ownGrokk, ownTyce, etc methods from another class depending on the value of the integer assigned to OwnedSpirits(int). This in turn fills arrays.
The problem is, I do this multiple times, and doing it from another class it seems like I have to make a new object every time to pass the new int argument, and doing so resets the value of spiritInstance. And, since that resets to zero, the arrays don't fill properly. I try to print out my array values later and I get an "ArrayIndexOutOfBoundsException".
public class OwnedSpirits {
private int spiritTypeInt = 0;
public static int spiritInstance=0;
public static int[] spiritarray = new int[9];
public static String[] spiritName = new String[9];
public static int[] party = new int[3];
public OwnedSpirits(int spiritcall){
if(spiritcall == 1){
ownGrokk();
}
if(spiritcall == 2){
ownRisp();
}
if(spiritcall == 3){
ownTyce();
}
if(spiritcall == 4){
ownDaem();
}
if(spiritcall == 5){
ownCeleste();
}
}
private void ownGrokk(){
spiritName[spiritInstance] = "Grokk";
spiritInstance++;
}
private void ownRisp(){
spiritName[spiritInstance] = "Risp";
spiritInstance++;
}
private void ownDaem(){
spiritName[spiritInstance] = "Daem";
spiritInstance++;
}
private void ownCeleste(){
spiritName[spiritInstance] = "Celeste";
spiritInstance++;
}
private void ownTyce(){
spiritName[spiritInstance] = "Tyce";
spiritInstance++;
}
and this code is in another class, where it attempts to call the methods to fill the array
buttonConfirm.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
if(xcounter==3){
for(x=0; x<3; x++){
if(setdaemtrue == true){
new OwnedSpirits(4);
}
if(setrisptrue == true){
new OwnedSpirits(2);
}
if(setcelestetrue == true){
new OwnedSpirits(5);
}
if(settycetrue == true){
new OwnedSpirits(3);
}
if(setgrokktrue == true){
new OwnedSpirits(1);
}
}
}
}
});
and finally in yet another class:
System.arraycopy(OwnedSpirits.spiritName, 0, partylist, 0, 3);
#Override
public void show() {
System.out.println(partylist[0]);
System.out.println(partylist[1]);
System.out.println(partylist[2]);
spiritlist.setItems(partylist);
table.add(spiritlist);
table.setFillParent(true);
stage.addActor(table);
}
If the last part is confusing, it's because I am using libgdx. the print statements are there just to try to figure out why my list was having an error
I can show you what I would do to handle Spirits, and Parties.
The Spirit class, contains name and current party its assigned to:
package com.stackoverflow.spirit;
public class Spirit {
private String name;
private Party party;
private SpiritType type;
private static int id = 0;
public static enum SpiritType {
Grokk, Risp, Tyce, Daem, Celeste
};
public Spirit(String name, SpiritType type) {
create(name, type);
}
public Spirit(SpiritType type) {
create(null, type);
}
// This is to handle Java inexistance of default parameter values.
private void create(String name, SpiritType type)
{
Spirit.id++;
this.name = (name == null) ? (type.name() + " " + id) : name;
this.type = type;
}
public String getName() {
return name;
}
public Party getParty() {
return party;
}
public SpiritType getType() {
return type;
}
/**
* Used internally by #see Party
* #param party the party this Spirit belongs
*/
public void setParty(Party party) {
this.party = party;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString()
{
return this.name;
}
}
Finally the Party class, contains a set of Spirits, you can add and remove Spirits from the party.
package com.stackoverflow.spirit;
import java.util.HashSet;
public class Party {
private HashSet<Spirit> spirits = new HashSet<Spirit>();
private static int id = 0;
private String name = "Party " + Party.id++;;
public Party() {
}
public Party(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void add(Spirit spirit) {
if (!spirits.contains(spirit)) {
spirits.add(spirit);
if (spirit.getParty() != null) {
//Remove from previous party to update the other party set
spirit.getParty().remove(spirit);
}
spirit.setParty(this);
} else {
// throw new SpiritAlreadyOnParty();
}
}
public void remove(Spirit spirit)
{
if (spirits.contains(spirit))
{
spirit.setParty(null); // You could create a default empty party for "Nature/Neutral" Spirits perhaps :)
spirits.remove(spirit);
}
else {
//throw new SpiritNotInParty();
}
}
public boolean isOnParty(Spirit spirit) {
return spirits.contains(spirit);
}
public ArrayList<Spirit> getSpirits()
{
return new ArrayList<Spirit>(spirits);
}
public int getPartySize() {
return spirits.size();
}
public String getPartyInfo()
{
StringBuilder builder = new StringBuilder();
builder.append("Party:" + this.name + " Size:" + this.spirits.size() + "\n");
for (Spirit s : spirits)
{
builder.append(s.getName() + "\n");
}
return builder.toString();
}
#Override
public String toString()
{
return this.name;
}
}
Here I use the Spirit and Party classes, you could add more functionality, like properties for party strength, magic buffs on the party, etc:
package com.stackoverflow.spirit;
import com.stackoverflow.spirit.Spirit.SpiritType;
public class Main {
public static void main(String[] args) throws java.lang.Exception {
Party griffindor = new Party("Griffindor"), slytherin = new Party(
"Slytherin");
// You can also do for (SpiritType type : SpiritType.values() then
// type.ordinal()
for (int i = 0; i < SpiritType.values().length; i++) {
griffindor.add(new Spirit(SpiritType.values()[i]));
slytherin.add(new Spirit(SpiritType.values()[i]));
}
Spirit mySpirit = new Spirit("NotAHPFan", SpiritType.Celeste);
slytherin.add(mySpirit);
System.out.println("Name of party:" + mySpirit.getParty().getName());
System.out.println("Is on griffindor?:"
+ griffindor.isOnParty(mySpirit));
// What now?
griffindor.add(mySpirit);
System.out.println("Is " + mySpirit.getName() + " on "
+ slytherin.getName() + "?:" + slytherin.isOnParty(mySpirit));
System.out.println(mySpirit.getName() + " is now on "
+ mySpirit.getParty() + "\n");
System.out.println(griffindor.getPartyInfo());
System.out.println(slytherin.getPartyInfo());
}
}
P.D: I'm not a HP fan.

HashSet removes duplicates but TreeSet does not?

Output of below class is :
size is 3
size is 1
But if I change the TreeSet to a HashSet so line :
Set<SuggestionDetailBean> set = new TreeSet<SuggestionDetailBean>();
becomes
Set<SuggestionDetailBean> set = new HashSet<SuggestionDetailBean>();
the output is :
size is 3
size is 2
Shout using HashSet or TreeSet not change the size of Set ?
Using HashSet seems to behave as expected because it is removing duplicates but when I use TreeSet the duplicates remain ?
I think the hashcode and equals methods in SuggestionDetailBean are overriden correctly ?
Here is the code :
public class TestSet {
public static void main(String args[]){
SuggestionDetailBean s = new SuggestionDetailBean();
s.setTagList("teddst");
s.setUrl("testurl");
SuggestionDetailBean s2 = new SuggestionDetailBean();
s2.setTagList("teddst");
s2.setUrl("testurl");
SuggestionDetailBean s3 = new SuggestionDetailBean();
s3.setTagList("tessdafat");
s3.setUrl("fdfaasdfredtestur ldd");
List<SuggestionDetailBean> list = new ArrayList<SuggestionDetailBean>();
list.add(s);
list.add(s2);
list.add(s3);
Set<SuggestionDetailBean> set = new TreeSet<SuggestionDetailBean>();
set.addAll(list);
System.out.println("size is "+list.size());
System.out.println("size is "+set.size());
}
}
public class SuggestionDetailBean implements Comparable<Object> {
private String url;
private String tagList;
private String numberOfRecommendations;
private String date;
private String time;
private String summary;
private String truncatedUrl;
public void setTruncatedUrl(String truncatedUrl) {
if(truncatedUrl.length() > 20){
truncatedUrl = truncatedUrl.substring(0, 20)+"...";
}
this.truncatedUrl = truncatedUrl;
}
public String getSummary() {
if(summary == null){
return "";
}
else {
return summary;
}
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public String getTruncatedUrl() {
return this.truncatedUrl;
}
public void setTime(String time) {
this.time = time;
}
public String getTagList() {
if(tagList == null){
return "";
}
else {
return tagList;
}
}
public void setTagList(String tagList) {
this.tagList = tagList;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getNumberOfRecommendations() {
return numberOfRecommendations;
}
public void setNumberOfRecommendations(String numberOfRecommendations) {
this.numberOfRecommendations = numberOfRecommendations;
}
#Override
public int compareTo(Object o) {
DateFormat formatter;
Date date1 = null;
Date date2 = null;
SuggestionDetailBean other = (SuggestionDetailBean) o;
if(this.date == null || other.date == null){
return 0;
}
formatter = new SimpleDateFormat(SimpleDateFormatEnum.DATE.getSdfType()+" "+SimpleDateFormatEnum.TIME.getSdfType());
try {
date1 = (Date) formatter.parse(this.date + " " + this.time);
date2 = (Date) formatter.parse(other.date + " " + other.time);
} catch (ParseException e) {
System.out.println("Exception thrown in"+this.getClass().getName()+", compareTo method");
e.printStackTrace();
}
catch(NullPointerException npe){
System.out.println("Exception thrown "+npe.getMessage()+" date1 is "+date1+" date2 is "+date2);
}
return date2.compareTo(date1);
}
#Override
public int hashCode() {
return this.url.hashCode();
}
#Override
public boolean equals(Object obj) {
SuggestionDetailBean suggestionDetailBean = (SuggestionDetailBean) obj;
if(StringUtils.isEmpty(this.getTagList())){
return this.getUrl().equals(suggestionDetailBean.getUrl());
}
else {
return (this.getTagList().equals(suggestionDetailBean.getTagList())) &&
(this.getUrl().equals(suggestionDetailBean.getUrl()));
}
}
}
Edit :
Note : if I convert the hashset to a treeset using :
Set<SuggestionDetailBean> sortedSet = new TreeSet<SuggestionDetailBean>(hashset);
Then correct sorting is maintained, as the removal of duplicates is based on the object hashcode and equals methods not the compareto method.
According to the Javadoc for TreeSet:
Note that the ordering maintained by a set (whether or not an explicit
comparator is provided) must be consistent with equals if it is to
correctly implement the Set interface. (See Comparable
or Comparator for a precise definition of consistent with
equals.) This is so because the Set interface is defined in
terms of the equals operation, but a TreeSet instance
performs all element comparisons using its compareTo (or
compare) method, so two elements that are deemed equal by this method
are, from the standpoint of the set, equal. The behavior of a set
is well-defined even if its ordering is inconsistent with equals; it
just fails to obey the general contract of the Set interface.
So, the problem is with your compareTo method: either it's giving inconsistent results, or else it's giving consistent results that don't obey the rule that a.compareTo(b) == 0 if and only if a.equals(b).
For example, this bit:
if(this.date == null || other.date == null){
return 0;
}
means "if either this or other has date == null, then report that this and other are equal", which is certainly not what you want.

Categories

Resources