Android-Java- How to Sort a List of Objects by a Certain Value Within the Object

Android-java- How to sort a list of objects by a certain value within the object

You should use Comparable instead of a Comparator if a default sort is what your looking for.

See here, this may be of some help - When should a class be Comparable and/or Comparator?

Try this -

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TestSort {

public static void main(String args[]){

ToSort toSort1 = new ToSort(new Float(3), "3");
ToSort toSort2 = new ToSort(new Float(6), "6");
ToSort toSort3 = new ToSort(new Float(9), "9");
ToSort toSort4 = new ToSort(new Float(1), "1");
ToSort toSort5 = new ToSort(new Float(5), "5");
ToSort toSort6 = new ToSort(new Float(0), "0");
ToSort toSort7 = new ToSort(new Float(3), "3");
ToSort toSort8 = new ToSort(new Float(-3), "-3");

List<ToSort> sortList = new ArrayList<ToSort>();
sortList.add(toSort1);
sortList.add(toSort2);
sortList.add(toSort3);
sortList.add(toSort4);
sortList.add(toSort5);
sortList.add(toSort6);
sortList.add(toSort7);
sortList.add(toSort8);

Collections.sort(sortList);

for(ToSort toSort : sortList){
System.out.println(toSort.toString());
}
}

}

public class ToSort implements Comparable<ToSort> {

private Float val;
private String id;

public ToSort(Float val, String id){
this.val = val;
this.id = id;
}

@Override
public int compareTo(ToSort f) {

if (val.floatValue() > f.val.floatValue()) {
return 1;
}
else if (val.floatValue() < f.val.floatValue()) {
return -1;
}
else {
return 0;
}

}

@Override
public String toString(){
return this.id;
}
}

sort List of Object by one of Object's field

You need to implement a Custom Comparator like the following

public class ContactComparator implements Comparator<Contact> {
public int compare(Contact contact1, Contact contact2) {
//In the following line you set the criterion,
//which is the name of Contact in my example scenario
return contact1.getName().compareTo(contact2.getName());
}
}

Then all you need is to call it like this (anywhere in your code where you need to have your contacts sorted):

Collections.sort(myContacts, new ContactComparator());

myContacts is the list of Contact objects you need to sort (you name it list in your question).

Sorting List of objects in android

Use Collection.sort and pass your own implementation of Comparator

Example:

List<Country> items = new ArrayList<Country>();

.....
Collections.sort(items, new Comparator<Country>() {

@Override
public int compare(Country o1, Country o2) {
return Double.compare(o1.getDistance(), o2.getDistance());
}

});

Sorting a listview of objects with value of the object itself - After a Query in DB

Perhaps this could help

   class myAdapter extends BaseAdapter {

private List<String> mList;

public void setList(List<String> list){
mList.clear();
mList.addAll(list);
sortMyList();
}

private void sortMyList() {
//Do sorting of the list

notifyDataSetChanged();
}

@Override
public int getCount() {
return 0;
}

@Override
public Object getItem(int position) {
return null;
}

@Override
public long getItemId(int position) {
return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
}

You could then call

myAdapter.setList(list);

which will set the list and sort it.

Sorting:

Collections.sort(empList, new Comparator<Employee>(){
public int compare(Employee emp1, Employee emp2) {
return emp1.getFirstName().compareToIgnoreCase(emp2.getFirstName());
}
});

taken from here: Android-java- How to sort a list of objects by a certain value within the object

Sorting list of custom objects wrt a property in android studio (API level problem)

You could create Long objects for the times and compare them directly:

Collections.sort(news, new Comparator<NewsItem>() {
@Override
public int compare(NewsItem newsItem1, NewsItem newsItem2) {
return Long.valueOf(newsItem2.getUpdateTime()).compareTo(
Long.valueOf(newsItem1.getUpdateTime()));
}
});

As a side note - API level 16 is quite outdated, and you may want to consider upgrading your requirements.

Sorting List of Objects by long property

Look at the definition of Long#compare :

public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

Similary, you simply can return 1 if the value greater than the other value, 0 if equals and -1 if less than:

Collections.sort(priceList, new Comparator<MyObject>() {
@Override
public int compare(MyObject o1, MyObject o2) {
return (o1.getPrice() < o2.getPrice()) ? -1 : ((o1.getPrice() == o2.getPrice()) ? 0 :1 );
});

Sort a Java collection object based on one field in it

here is my "1liner":

Collections.sort(agentDtoList, new Comparator<AgentSummaryDTO>(){
public int compare(AgentSummaryDTO o1, AgentSummaryDTO o2){
return o1.getCustomerCount() - o2.getCustomerCount();
}
});

UPDATE for Java 8:
For int datatype

 Collections.sort(agentDtoList, (o1, o2) -> o1.getCustomerCount() - o2.getCustomerCount());

or even:

 Collections.sort(agentDtoList, Comparator.comparing(AgentSummaryDTO::getCustomerCount));

For String datatype (as in comment)

Collections.sort(list, (o1, o2) -> (o1.getAgentName().compareTo(o2.getAgentName())));

..it expects getter AgentSummaryDTO.getCustomerCount()

Java sort array of objects by integer field and if those are identical then sort by another integer value

Try to customize the compare method.
e.g.

if(o1.getPriority() != o2.getPriority()) 
return Integer.valueOf(o1.getPriority()).compareTo(o2.getPriority());

if(o1.getTime() != o2.getTime())
return Integer.valueOf(o1.getTime()).compareTo(o2.getTime());

return 0; //they are equal with all fields

Android - java - how to sort a list of object byan GregorianCalendar argument

EDIT I completly overhauled my answer in response to the new edit on your question.

The problem is that for each Evento that populates your listEventos1, you're using the same Calendar (variable name day). You're doing this:

list.add(setEvento(day, "Certain Tuesday”, "do this"));

And then this:

day.add(Calendar.DAY_OF_MONTH, 1); 
list.add(setEvento(day, "Certain Wendsday”, "do that"));

But what the call to Calendar#add does is it

Adds or subtracts the specified amount of time to the given calendar
field, based on the calendar's rules.

In other words, Calendar is a mutable class, i.e. it can change states, unlike a String, which is immutable and will always be the same. Don't worry, you're not the first to make that mistake, and that's partly why Java introduced a new Date API (more precisely, it's because that made the classes not thread-safe).

So in other words, whenever you're calling the Calendar#add method, all objects in listEventos1 change, because they all contain the same instance of Calendar. For a really good example of why this happens, see this answer.

One way to verify this is to add a supplementary check in your Comparator by using the == operator. == will return true if the two variables point to the same instance:

Collections.sort(listEventosAll,  new Comparator<Evento> (){
public int compare(Evento evento1, Evento evento2) {
if(evento1.date.getTime() == evento2.date.getTime())
System.out.println("Warning! Two references pointing to the same object!");
if (evento1.date.getTime() == null || evento2.date.getTime() == null)
return 0;
return evento1.date.getTime().compareTo(evento2.date.getTime());
}

Running this with your current code should output a bunch of warnings.

Another tidbit of information: according to the Javadoc of Comparator, Comparator#compare should throw a NullPointerException if one of the arguments is null.


SOLUTION
To fix this problem, you need to pass different instances of Calendar at each call of setEvento. Some classes, such as those in the Collection API possess copy constructors, that is, constructors that will take an object as an argument, and return a new object with exactly the same values. Calendar doesn't implement copy constructors, but it does however implement the Cloneable interface, which means you can clone its objects.

Cloning is sometimes frowned upon in the Java world, but in this specific case it's a viable option.

So here's how to clone day so that each time you call Evento, it points to a new object (this is your listEventos1 method):

list.add(setEvento(day, "Certain Tuesday", " do this "));
day = (Calendar) day.clone(); //This is what I added
day.add(Calendar.DAY_OF_MONTH, 1);

Naturally, repeat this for every object your insert.


NOTE: btw, some quotation marks in your code are closing English quotation marks () instead of double quotes ("). This will break your code.

OTHER NOTE: You're not using the inheritance mechanism correctly, and your code could be simplified by using Evento as a Calendar itself. But that's for another day.



Related Topics



Leave a reply



Submit