Im devoloping a program that i put some elements into my object within an ArrayList... this is my code
import java.util.ArrayList;
public class ListaConcepto {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<CompararListas> Lista = new ArrayList<CompararListas>();
CompararListas obj1 = new CompararListas("abc", 12.25, "lala", 2);
CompararListas obj2 = new CompararListas("abc", 13.50, "lala", 3);
CompararListas obj3 = new CompararListas("poc", 12.50, "jaja", 1);
Lista.add(obj1);
Lista.add(obj2);
Lista.add(obj3);
}
}
Then... this is my class with the interface Comparable... and i need a method to implement to see if elements are EQUALS then print the result.
public class CompararListas implements Comparable<CompararListas> {
private String referencia;
private double monto;
private String descripcion;
private double NumeroParte;
public CompararListas(String referencia, double monto, String descripcion, double numeroParte) {
this.referencia = referencia;
this.monto = monto;
this.descripcion = descripcion;
this.NumeroParte = numeroParte;
}
public double getMonto() {
return monto;
}
public void setMonto(double monto) {
this.monto = monto;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
public double getNumeroParte() {
return NumeroParte;
}
public void setNumeroParte(double numeroParte) {
NumeroParte = numeroParte;
}
public String getReferencia() {
return referencia;
}
public void setReferencia(String referencia) {
this.referencia = referencia;
}
#Override
public int compareTo(CompararListas o) {
// TODO Auto-generated method stub
return 0;
}
}
Remember Comparable is meant to be used to decide the relationship between to items for the purposes of ordering; it's not quite for equality. In fact, there's no requirement that any two comparable items must be equal.
In your case, you may want to order by NumeroParte, which means "Part Number" and seems like a sensible choice. Every type of data has a different way to be organized.
Your method may look something like
public int compareTo(ComprarListas o){
return this.NumeroParte - o.getNumeroParte();
}
Which works because both are integer numbers.
Or the appropriate property of your object - you may want to order based on price instead for instance.
If you want to know just if an object is equal to another you have to implemet the equals method (which doesn't requiere you to declare any interface, every class can do it)
#Override
public boolean equals(Object o) {
CompararListas other = (CompararListas) o;
return ...
}
with this method you can return what makes the two objects equals to you, if you just have to look for referencia.equals(other.referencia) or if you have to compare every property like referencia.equals(other.referencia) && monto == other.monto && ...
But if you want to compare elements in order to do something like ordering them there you have to implement the Comparable interface and implement the compareTo method
#Override
public int compareTo(CompararListas o) {
if (NumeroParte < o.NumeroParte)
return -1;
else if (NumeroParte > o.NumeroParte)
return 1;
return 0;
}
This will make the objects able to compare each other and for example know if one is "smaller" than other according to your criteria (in this example I only used NumeroParte and made it explicit to be easy to understand, but the key is that you can use any criteria you want to compare the objects and if you want order them later).
These are solutions to different problems, you have to identify which one is the better in your case.
Related
I've got a problem I am currently tring to parse a Json file and remove duplicate from it so i thought that i would store it in a Hashset of my Class that hold information but it doesnt remove duplicate.
Can you explain me if I did something wrong of if there is something that I don't understand?
here is a sample of my Code:
try {
FileReader f = new FileReader("E:\\JavaDev\\src\\main\\resources\\annonces.json");
JsonReader jsonReader = new JsonReader(f);
Gson gson = new Gson();
Appartement[] res2 = new Appartement[0];
res2 = gson.fromJson(jsonReader, res2.getClass());
Set<Appartement> test = new HashSet<Appartement>(Arrays.asList(res2));
System.out.println(test.size());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
My Appartment look like this:
(getter and setter are removed here to have smaller code)
public class Appartement {
private String id;
private Double surface;
private String marketingType;
private Integer roomCount;
private String propertyType;
private Boolean furnished;
private Boolean newBuild;
private String zipCode;
private Double price;
}
I tried converting my json directly in a Hashset but I've got an error: java.lang.OutOfMemoryError: Java heap space
HashSet<Appartement> mySet = gson.fromJson(jsonReader, HashSet.class);
I verified that there is duplicate in the Json file.
Would apreciate some help here.
You must override equals method of your Appartment class,
See here: Object equal method, if you don't override its default equal method, it actually compared the reference of the object,
public class Appartement {
private String id;
....
#Override
public boolean equals(Object obj) {
if (!(obj instanceof Appartement)) return false;
return this.id.equals(((Appartement)obj.id));
}
#Override
public int hashCode() {
return 123123131311; //replace to your own hashcode.
}
}
Joshua, Effective Java
You must override hashCode() in every class that overrides equals().
Failure to do so will result in a violation of the general contract
for Object.hashCode(), which will prevent your class from functioning
properly in conjunction with all hash-based collections, including
HashMap, HashSet, and Hashtable.
Set<Appartement> test = new HashSet<Appartement>(Arrays.asList(res2));
You must make sure that Apartment's hashcode and equals method are overridden and you return true from equals method for same Appartement. (based on its properties) otherwise Objects.equals will be called
You need to override equals method (requiring appropriate equality checking) and hascode method in your Appartement.class
import java.util.*;
public class HelloWorld{
public static void main(String []args){
System.out.println("Hello World");
Appartement[] res2 = {(new HelloWorld()).new Appartement("1"), (new HelloWorld()).new Appartement("2"), (new HelloWorld()).new Appartement("3"),(new HelloWorld()).new Appartement("1") };
Set<Appartement> test = new HashSet<Appartement>(Arrays.asList(res2));
System.out.println(test.size());
}
public class Appartement {
private String id;
private Double surface;
private String marketingType;
private Integer roomCount;
private String propertyType;
private Boolean furnished;
private Boolean newBuild;
private String zipCode;
private Double price;
public Appartement(String id){
this.id=id;
}
#Override
public boolean equals (Object other)
{
if (!(other instanceof Appartement))
return false;
Appartement ob = (Appartement) other;
return this.id.equals(ob.id) ;
}
#Override
public int hashCode ()
{
return Arrays.hashCode(new String[]{id});
}
}
}
I have a class name "Users" and have 2 elements (int)userId and (String)userName.
Let's said
Users obj1 = new Users(10, "User1");
Users obj2 = new Users(11, "User2");
So I want to compare obj1 to obj2
element by element
10 compare to 11,
"User1" compare to "User2".
From the research i do from web. It looks like impossible to do it whether convert it to 2d array to compare or whatever method. Is there any method to do this kind of things?
I actually want to do an audit trail so i have the object before changes and after changes, so whatever element that have changed will insert a new record in the audit_trail table with the before value and after value.
I'm a newbie to programming i tried my best to think a way but it just doesn't work. Is there any other way of doing this by SQL? i using ng-admin as (front-end) and API java http to do a update (back-end).
You need to implement the Comparable<Users> interface. If you want equality check too, then you have to override
boolean equals(Object)
and
int hashCode()
Read:
https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html
and
Why do I need to override the equals and hashCode methods in Java?
From your question, We can compare two different objects.
Please implement the equals method to do your operations available in Comparable<Users>.
Let's say as a example below,
Class obj1 = new Class(1, "raja");
Class obj2 = new Class(2, "thiru");
The id and name are a public variable of the class. Then
override the function as,
public boolean equals(Object obj)
{
return (this.id == obj.id && this.name.equals(obj.name.equals));
}
Thanks.
You should override the .equals() method, making your Users class as follows:
public class Users {
private int mId;
private String mName;
public Users(int pId, String pName) {
mId = pId;
mName = pName;
}
public int getId() {
return mId;
}
#Override
public boolean equals(Object pObject) {
return (pObject instanceof Users && ((Users) pObject).getId() == mId);
}
}
I'd probably create a BeanDelta object
public class PropertyDelta {
private String propertyName;
private Object value1;
private Object value2;
// constructor & getters
}
public class BeanDelta<T> {
private Class<T> type;
private List<PropertyDelta> propertyDeltas = new ArrayList<>();
public BeanDelta(Class<T> type) {
this.type = type;
}
// getters
}
Then you could write a reflection based method
public <T> BeanDelta<T> getDelta(T o1, T, o2) {
Class<T> type = o1.getClass();
Method[] methods = type.getMethods();
BeanDelta<T> delta = new BeanDelta<>(type);
for (Method meth : methods) {
boolean isGetter = method.getParameterTypes().length == 0 && !method.getReturnType().equals(void.class) && meth.getName().startsWith("get");
if (isGetter) {
Object v1 = meth.invoke(o1);
Object v2 = meth.invoke(o2);
if (!Objects.equal(v1, v2)) {
String propertyName = meth.getName().substring(3);
delta.propertyDeltas.add(new PropertyDelta(propertyName, v1, v2));
}
}
}
return delta;
}
Check it out the solution proposed for do that.
http://www.codejava.net/java-core/collections/sorting-a-list-by-multiple-attributes-example
I have an ArrayList<HashMap<String,String>> and I want to sort it. My ArrayList output in Logcat is like this:
[{num=0, username=p, startPoliPro=A, finalPoliPro=B, diff=0},
{num=1, username=e, startPoliPro=C, finalPoliPro=D, diff=548.0Km},
{num=2, username=e, startPoliPro=E, finalPoliPro=F, diff=3.0Km}]
I want to sort the list based on "diff" value by ascending order so that Logcat has to be like:
[{num=0, username=p, startPoliPro=A, finalPoliPro=B, diff=0},
{num=2, username=e, startPoliPro=E, finalPoliPro=F, diff=3.0Km},
{num=1, username=e, startPoliPro=C, finalPoliPro=D, diff=548.0Km}]
I have read many similar topics and tried something like
Collections.sort(final_itinList, new Comparator<HashMap< String,String >>() {
#Override
public int compare(HashMap<String, String> lhs, HashMap<String, String> rhs) {
// Do your comparison logic here and retrn accordingly.
return lhs.get("diff").compareTo(rhs.get("diff"));
}
});
with no success. Any help would be appreciated
Currently, you are trying to compare two String Objects:
return lhs.get("diff").compareTo(rhs.get("diff"));
What you really want to do is comparing the returned Integers, so you would need to do something like this:
return (Integer.parseInt(lhs.get("diff")) - Integer.parseInt(rhs.get("diff")));
Your Comparator is comparing two Strings. That's probably why the list is not sorted correctly. The "diff" string should be parsed as an integer (or float) to compare it.
If your objects always have the same structure, I would advise to create a List of a custom object (where the diff is an integer representing the number of kilometers) instead of using a List of Maps. In that case, you could make your custom object implement Comparable.
Something like :
public class MyCustomObject implements Comparable<MyCustomObject> {
private String mNum;
private String mUsername;
private String mStartPoliPro;
private String mFinalPoliPro;
private int mDiff;
#Override
public int compareTo(MyCustomObject another) {
return mDiff - another.getDiff();
}
public String getNum() {
return mNum;
}
public void setNum(String num) {
mNum = num;
}
public String getUsername() {
return mUsername;
}
public void setUsername(String username) {
mUsername = username;
}
public String getStartPoliPro() {
return mStartPoliPro;
}
public void setStartPoliPro(String startPoliPro) {
mStartPoliPro = startPoliPro;
}
public String getFinalPoliPro() {
return mFinalPoliPro;
}
public void setFinalPoliPro(String finalPoliPro) {
mFinalPoliPro = finalPoliPro;
}
public int getDiff() {
return mDiff;
}
public void setDiff(int diff) {
mDiff = diff;
}
}
and then simply call
List<MyCustomObject> myList = // create your object list
Collections.sort(myList);
I have a list of custom entities which I need to sort in this order: valueOne, valueTwo, and valueThree.
Here is my code
public class AppRunner {
public static void main(String[] args) {
Detail d1 = new Detail("valueOne");
Detail d2 = new Detail("valueTwo");
Detail d3 = new Detail("valueFive");
Detail d4 = new Detail("valueTen");
Detail d5 = new Detail("valueOne");
Detail d6 = new Detail("valueOne");
List<Detail> details = new ArrayList<Detail>(Arrays.asList(d1, d2, d3, d4, d5, d6));
Collections.sort(details);
System.out.println(details);
}
}
My entity class
public class Detail implements Comparable<Detail> {
private String value; // there are three options: valueOne, valueTwo, and some other value
public Detail(String value) {
this.value = value;
}
#Override
public int compareTo(Detail detail) {
String val = detail.getValue();
if (val.equals(this.value) && val.equals("valueOne")) {
return 1;
} else if (val.equals(this.value) && val.equals("valueTwo")) {
return -1;
} else {
return 0;
}
}
// getter, setters, toString
}
I think that need help with compareTo method. In the end I need to get list in this order:
valueOne
valueOne
valueOne
valueTwo
valueFive
Use an Enum and compare ordinals:
enum ValidValues { valueOne, valueTwo, valueThree }
... and then:
public int compareTo(Object detail) {
return Integer.compare(ValidValues.valueOf(this.value).ordinal(),
ValidValues.valueOf(((Detail)detail).value).ordinal());
}
For a larger number of values it might be worth it to do this with a collection or map, rather than an enum.
You can have a simple getter that return a numeric value based on your String value and simply return the difference of both numeric values in your compare() method (remember that compare() should return 0 if the two objects are equals, see Comparable javadoc.
public static class Detail implements Comparable<Detail> {
private String value; // there are three options: valueOne, valueTwo, and some other value
public Detail(String value) {
this.value = value;
}
#Override
public int compareTo(Detail detail) {
return this.getNumericValue() - detail.getNumericValue();
}
private int getNumericValue() {
switch (this.value) {
case "valueOne": return 1;
case "valueTwo": return 2;
default: return 3;
}
}
}
See note at the end on possible better designs.
I suggest adding another field to the Detail class, populating that baeed on the desired sort order and value, and using this to sort.
public class Detail implements Comparable<Detail> {
private String value;
private int sortOrder;
public Detail(String value) {
this.value = value;
if(value.equals("valueOne") {
sortOrder = 1;
}
if(value.equals("valueTwo") {
sortOrder = 2;
}
...
...
}
This makes compareTo simple:
public int compareTo(Detail detail) {
if(this.sortOrder < detail.sortOrder) {
return -1;
}
if(this.sortOrder == detail.sortOrder) {
return 0;
}
if(this.sortOrder > detail.sortOrder) {
return 1;
}
}
Note:
The above is solution to your problem as it stands. However, you may have better options. If you are using Detail to represnet a fixed set of values, look at Enums. Enums in Java are very powerful and versatile. You can have a enum repsesenting a fixed set of values and use the enum in your Detail class.
If you may have a large set of values that are not predefined, you can have a Map that maps the sort order with the value.
private static Map<Int, String> sortOrder = new HashMap<Int, String>();
sortOrder.put(1, "valueOne");
...
And use this map sorting. Depending on your situation, you can popuklate this map from a database, a file on initialization or just dueing runtime.
I know this has be discussed over and over again here, but none of the examples I've tried worked for me.
What I've got
I access the Call log from Android and I get a list of all calls made. Of course, here I get a lot of duplicates.
First I make a List
List<ContactObject> lstContacts = new ArrayList<ContactObject>();
Then I add objects into it
While (get some record in call log)
{
ContactObject contact = new ContactObject();
contact.SetAllProperties(......)
lstContacts.add(contact);
}
Set<ContactObject> unique = new LinkedHashSet<ContactObject>(lstContacts);
lstContacts = new ArrayList<ContactObject>(unique);
The Contact Object class is simple
public class ContactObject {
public ContactObject() {
super();
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof ContactObject))
return false;
return this.lstPhones == ((ContactObject) obj).getLstPhones();
}
#Override
public int hashCode() {
return lstPhones.hashCode();
}
private long Id;
private String name;
private List<String> lstPhones;
private String details;
//... getters and settres
}
What I need
I need to have a Contact only once in the list. As I've read around here there are a couple of things that can be done like Set, HashSet, TreeSet. TreeSet seems the best as it keeps the order just as I receive it from the Call log. I've tried to make my code work with it but no success. Could anyone be so kind to give me a sample code based on my example. Thank you for your time.
The Working Solution. Thank you all for your support, you've made my day.
In ContactObject override the two methods
#Override
public boolean equals(Object obj) {
if (!(obj instanceof ContactObject))
return false;
return lstPhones.equals(((ContactObject) obj).getLstPhones());
}
#Override
public int hashCode() {
return (lstPhones == null) ? 0 : lstPhones.hashCode();
}
//Getters and Setters and COnstructor....
Simply use it as
Set<ContactObject> unique = new LinkedHashSet<ContactObject>(lstContacts);
lstContacts = new ArrayList<ContactObject>(unique);
LinkedHashSet which keeps insertion-order can be used in your case.
HashSet: no order.
TreeSet: sorted set, but not keep insertion order.
EDIT: As Software Monkey commented, hashCode() and equals() should be overwritten in ContactObject to fit the hash-based Set.
Remove duplication of Custom Object
Example of Removing duplicate using Comparator
Lets suppose you have a class "Contact"
public class Contact implements Comparable<Contact> {
public String getName() {
return this.Name;
}
public void setName(String name) {
this.Name = name;
}
public String getNumber() {
return this.Number;
}
public void setNumber(String number) {
this.Number = number;
}
///// this method is very important you must have to implement it.
#Override
public String toString() {
return "\n" +"Name=" + name + " Number=" + Number;
}
Here is how you can remove duplicate entries using Set , just pass your list in the function and it will work for you. New list will be returned which will have no duplicated contacts.
public ArrayList<Contact> removeDuplicates(ArrayList<Contact> list){
Set<Contact> set = new TreeSet(new Comparator<Contact>() {
#Override
public int compare(Contact o1, Contact o2) {
if(o1.getNumber().equalsIgnoreCase(o2.getNumber())){
return 0;
}
return 1;
}
});
set.addAll(list);
final ArrayList newList = new ArrayList(set);
return newList;
}
It worked for me so please try and give me your feedback. Thanks
P.S: Credit goes to Nilanchala at this article
For sure you can use TreeSet to store only once but a common mistake is do not override hashCode() and equal() methods:
This can fit for you:
public boolean equals(Object obj) {
if (!(obj instanceof ContactObject))
return false;
return this.id == ((ContactObject) obj).getId(); // you need to refine this
}
public int hashCode() {
return name.hashCode();
}
List<ContactObject> listContacts = new ArrayList<ContactObject>();
//populate...
//LinkedHashSet preserves the order of the original list
Set<ContactObject> unique = new LinkedHasgSet<ContactObject>(listContacts);
listContacts = new ArrayList<ContactOjbect>(unique);
Use Set's instead.
Set's works as an Mathematical collection, so it doesn't allow duplicated elements.
So it checks the equality and the .equals() methods for each element each time you add an new element to it.