What's alternative NSSortDescriptor in Java? - java

I hava ArrayList which is include Custom Data Class.
ArrayList<MyData> list
Custom Data class has several field
class MyData {
private int num;
private String name;
etc....
getter/setter...
}
I want to sort List by field (ex:num)
Objecitive-C has NSSortDescriptor which can sort objects.
NSSortDescriptor Class Reference
is There alternative this? or other solution?

You can use Comparable and Comparator interface.. and the use Collection.sort().
You need to implement Comparable and Comparator interface, if you are using Collection of Custom Type(i.e not primitive types).
For detailed examples check http://www.mkyong.com/java/java-object-sorting-example-comparable-and-comparator/
Hope this post will be helpful to u.

Implement Comparable or Comparator and use Collections.sort().
Comparable
public class MyClass implements Comparable<MyClass>{
public int x;
public int compareTo(MyClass mc){
return x - mc.x;
}
}
Comparator
public class MyClass{
public int x;
}
public class MyClassComparator implements Comparator<MyClass>{
public int compare(MyClass mc1, MyClass mc2){
return mc1.x - mc2.x;
}
}

java.util.Comparator coupled with java.util.Collection.sort should do the trick.
You could also have MyData implement java.util.Comparable and use the other sort method, but that isn't quite as flexible.

There is nothing similar to NSSortDescriptor in Java: Java sorting uses the style that is more similar to the sortUsingComparator: method of the NSMutableArray class:
Collections.sort(list, new Comparator<MyData>() {
// This is similar to the comparator block of Cocoa
public int compare(MyData o1, MyData o2) {
// Put the comparison code here
...
}
});

Related

Sort Nodes by an attribute in Graphstream [duplicate]

This question already has answers here:
Sorting an ArrayList of objects using a custom sorting order
(12 answers)
Closed 6 years ago.
If I have a simple list of Strings:
List<String> stringList = new ArrayList<String>();
I can sort it with:
Collections.sort(stringList);
But suppose I have a Person class:
public class Person
{
private String name;
private Integer age;
private String country;
}
And a list of it:
List<Person> personList = new ArrayList<Person>();
And I want to sort it sometimes by name, sometimes by age, sometimes by country.
What is the easiest way to accomplish that?
I know that I can implement the Comparable interface, but that seems to limit me to sort it by one specific property.
Collections.sort can be called with a custom comparator. And that comparator can be implemented to allow sorting in different sort orders. Here's an example (for your Person model - with age as an Integer):
public class FlexiblePersonComparator implements Comparator<Person> {
public enum Order {Name, Age, Country}
private Order sortingBy = Name;
#Override
public int compare(Person person1, Person person2) {
switch(sortingBy) {
case Name: return person1.name.compareTo(person2.name);
case Age: return person1.age.compareTo(person2.age);
case Country: return person1.country.compareTo(person2.country);
}
throw new RuntimeException("Practically unreachable code, can't be thrown");
}
public void setSortingBy(Order sortBy) {
this.sortingBy = sortingBy;
}
}
And you use it like that (assuming persons is a field):
public void sortPersonsBy(FlexiblePersonComparator.Order sortingBy) {
List<Person> persons = this.persons; // useless line, just for clarification
FlexiblePersonComparator comparator = new FlexiblePersonComparator();
comparator.setSortingBy(sortingBy);
Collections.sort(persons, comparator); // now we have a sorted list
}
Implement the Comparator interface (once for each different sort order) and use the Collections.sort() method that takes a Comparator as additional parameter.
Thanks to the responders. For the benefit of others, I'd like to include a complete example.
The solution is the create the following additional classes:
public class NameComparator implements Comparator<Person>
{
public int compare(Person o1, Person o2)
{
return o1.getName().compareTo(o2.getName());
}
}
public class AgeComparator implements Comparator<Person>
{
public int compare(Person o1, Person o2)
{
return o1.getAge().compareTo(o2.getAge());
}
}
public class CountryComparator implements Comparator<Person>
{
public int compare(Person o1, Person o2)
{
return o1.getCountry().compareTo(o2.getCountry());
}
}
The list can then be sorted like this:
Collections.sort(personList, new NameComparator());
Collections.sort(personList, new AgeComparator());
Collections.sort(personList, new CountryComparator());
The Java 8 way of doing this is to use List.sort as follows:
personList.sort(Comparator.comparing(Person::getName));
To quote Stuart Marks in his answer over here.
This is the big advantage of the List.sort(cmp) extension method over Collections.sort(list, cmp). It might seem that this is merely a small syntactic advantage being able to write myList.sort(cmp) instead of Collections.sort(myList, cmp). The difference is that myList.sort(cmp), being an interface extension method, can be overridden by the specific List implementation. For example, ArrayList.sort(cmp) sorts the list in-place using Arrays.sort() whereas the default implementation implements the old copyout-sort-copyback technique.
You could also use the BeanComparator from apache commons beanutils, like this:
Collections.sort(personList, new BeanComparator("name"));
Implement 3 different types of Comparator.
you can add the comparator to the sort command. The comparator you define, will sort the elements by name, age, or what ever.
Collections.sort(list, new Comparator() {
public int compare(Object arg0, Object arg1) {
if (!(arg0 instanceof Person)) {
return -1;
}
if (!(arg1 instanceof Person)) {
return -1;
}
Person pers0 = (Person)arg0;
Person pers1 = (Person)arg1;
// COMPARE NOW WHAT YOU WANT
// Thanks to Steve Kuo for your comment!
return pers0.getAge() - pers1.getAge();
}
});
The Collections.sort method can be invoked with a second argument which is the comparator to use.
Create 3 comparators and use the one you want when appropriate.
Collections.sort(list , new Comparator() {
public int compare(Object o1, Object o2) {
...
}
});
Using lambdaj ( http://code.google.com/p/lambdaj/ ) you can achieve what you're asking in the following way:
sort(personList, on(Person.class).getName());
sort(personList, on(Person.class).getAge());
sort(personList, on(Person.class).getCountry());
I asked a very similar question (about searching rather than sorting), perhaps there is some useful information (I ended up using an enum that implements Comparator so I pass the enum value as a comparator selector).

How can I use lambda expressions in a Comparator class in Java

I am fairly new to Java and now I have to create some Comparator classes.
On this Stackoverflow page I have found some really useful information about using lambda expressions. How to compare objects by multiple fields
Which made me thing about creating a Compartor class like this:
public class WidthComparator implements Comparator{
#Override
public int compare(Object t, Object t1) {
Foto foto1 = (Foto)t;
Foto foto2 = (Foto)t1;
return Comparator.comparing(Foto::getWidth)
.thenComparing(Foto::getHeight)
.thenComparingInt(Foto::getName);
}
}
}
so when I have a collection called fotosCollection, I would like to be able to do this:
fotosCollection.sort(new HoogteComparator());
This obviously does not work, but how could I get this to work?
Ps. I have to use a Comparator class.
Comparator.comapring returns a Comparator - you can just use it directly:
// Define a "constant" comparator
private static final Comparator<Foo> HOOGTE_COMPARATOR =
Comparator.comparing(Foto::getWidth)
.thenComparing(Foto::getHeight)
.thenComparingInt(Foto::getName);
// Use it elsewhere in your code
fotosCollection.sort(HOOGTE_COMPARATOR);
If you really don't want the comparator type to be anonymous for some reason, you can do:
public class WidthComparator implements Comparator<Foto>{
private final static Comparator<Foto> FOTO_COMPARATOR = Comparator.comparing(Foto::getWidth)
.thenComparing(Foto::getHeight)
.thenComparingInt(Foto::getName);
#Override
public int compare(Foto foto1, Foto foto2) {
return FOTO_COMPARATOR.compare(foto1, foto2);
}
}
I also would consider avoiding the use of the rawtype and implement Comparator<Foto> instead, as I did above.
You can try this old-style approach:
public class WidthComparator implements Comparator{
#Override
public int compare(Object t, Object t1) {
Foto foto1 = (Foto)t;
Foto foto2 = (Foto)t1;
// width asc order
if(foto1.getWidth() != foto2.getWidth())
return foto1.getWidth() - foto2.getWidth();
// height asc order
if(foto1.getHeight() != foto2.getHeight())
return foto1.getHeight() - foto2.getHeight();
// name asc order
return foto1.getName().compareTo(foto2.getName());
}
}

Java: Collections.sort resulting in error - no suitable method found [duplicate]

Hi need Help regarding java collection sorting. It gives me this error:
Bound mismatch: The generic method sort(List<T>) of type Collections is not applicable for the arguments (List<WifiSSID>).
The inferred type WifiSSID is not a valid substitute for the bounded parameter <T extends Comparable<? super T>>
My code looks like:
public class WifiSSID {
public String SSIS;
public double id;
}
public class ScanFilterWifiList {
public ScanFilterWifiList(List<WifiSSID> wifiList) {
Collections.sort(wifiList);
//Collections.sort(wifiList, new SortSSIDByid()); tried this also.
}
}
interface Comparator<WifiSSID>
{
int compare(WifiSSID obj1, WifiSSID obj2);
}
class SortSSIDByid implements Comparator<WifiSSID>
{
#Override
public int compare(WifiSSID ssid1, WifiSSID ssid2)
{
int value = 0;
if (ssid1.id > ssid2.id)
value = 1;
else if (ssid1.id < ssid2.id)
value = -1;
else if (ssid1.id == ssid2.id)
value = 0;
return value;
}
}
Am I doing anything wrong?
You can't sort a List of objects that don't implement the Comparable interface. Or rather, you can, but you have to provide a Comparator to the Collections.sort() method.
Think about it: how would Collections.sort() sort your list without knowing when a WifiSSID is smaller or bigger than another one?
You want to use Collections.sort(wifiList, new SortSSIDByid());
EDIT:
You defined your own proprietary Comparator interface, and implement this proprietary Comparator interface in SortSSIDByid. Collections.sort() wants an intance of java.util.Comparator. Not an instance of your proprietary Comparator interface, that it doesn't know.
Just add this import import java.util.Comparator;
and remove this interface
interface Comparator<WifiSSID>
{
int compare(WifiSSID obj1, WifiSSID obj2);
}
Your SortSSIDByid comparator class will now implement java.util.Comparator and that is what is required by the Collections.sort() method.

converting Comparable from and to Comparator?

I often have a Comparator type while I need a Comparable and the other way around. Is there a reusable JDK API to convert from one another? Something along the lines of:
public static <C> Comparable<C> toComparable(final Comparator<C> comparator) {
// does not compile because Hidden can not extend C,
// but just to illustrate the idea
final class Hidden extends C implements Comparable<C> {
#Override
public int compareTo(C another) {
return comparator.compare((C) this, another);
}
};
return new Hidden();
}
public static <C extends Comparable<C>> Comparator<C> toComparator(final Class<C> comparableClass) {
return new Comparator<C>() {
#Override
public int compare(C first, C second) {
assert comparableClass.equals(first.getClass());
assert comparableClass.equals(second.getClass());
return first.compareTo(second);
}
};
}
ComparableComparator from Apache Commons Collections seems to address Comparable<T> to Comparator problem (unfortunately its not generic type-friendly).
The reverse operation is not quite possible because the Comparator<T> represents algorithm while Comparable<T> represents actual data. You will need composition of some sort. Quick and dirty solution:
class ComparableFromComparator<T> implements Comparable<T> {
private final Comparator<T> comparator;
private final T instance;
public ComparableFromComparator(Comparator<T> comparator, T instance) {
this.comparator = comparator;
this.instance = instance;
}
#Override
public int compareTo(T o) {
return comparator.compare(instance, o);
}
public T getInstance() {
return instance;
}
}
Say you have class Foo that is not Comparable<Foo> but you have Comparator<Foo>. You use it like this:
Comparable<Foo> comparable = new ComparableFromComparator<Foo>(foo, comparator);
As you can see (especially without mixins) it's pretty ugly (and I'm not even sure if it'll work...) Also notice that comparable doesn't extend Foo, you have to call .getInstance() instead.
Since Java 8 the Comparator interface has had a few utility default methods added that assist with deriving a comparator from a comparable.
Consider the following example of sorting users by first name.
class Person {
String firstName;
String lastName;
}
List<Person> people = ...
people.sort(Comparator.comparing(Person::firstName));
You can obtain an instance of Comparator able to compare instance of Comparable type simply with
java.util.Comparator.naturalOrder()
see Comparator.naturalOrder()
this is a sort of conversion from Comparable to Comparator
Comparable items can be sorted as they have a compareTo:
Collection<Comparable> items;
Collections.sort(items);
If items are not Comparable, they need a Comparator object to do the comparison:
Collections<T> items;
Collections.sort(items, comparator);
A bridging Comparator is trivial, and you did it already.
Wrapping every T item with some Comparable adapter having a Comparator, seems useless.
First of all not inheritance but as field one needs to wrap the item.
public class CatorComparable<T> implements Comparable<CatorComparable<T>> {
public T value;
private Comparator<T> cator;
public CatorComparable(T value, Comparator<T> cator) {
this.value = value;
this.cator = cator;
}
#Override
public int compareTo(CatorComparable<T> other) {
return cator.compareTo(value, other.value);
}
}
Too much overhead.
I don't think you can really convert between them, nor does it really make sense to, since Comarable is a property of the class itself, while Comparator is an external class.
The best bet would be to write some sort of utility class that contains the underlying comparison logic (and probably have that implement Comparator), then use that class as a part of the logic for the Comparable implementation on the class itself.

Sorting problem cannot instantiate abstract object overriding compareTo() Method

I'm trying to establish a new sort criteria, in this case by name.
I'm facing an error when I call the sort method...
this is a separated class (SortByName) in package "package":
-----------------------CLASS SortByName---------------------------
package package;
import java.util.*;
public abstract class SortByName implements Comparator{
public int compareTo(Object o1, Object o2){
String n1 = ((Ficha)o1).getName();
String n2 = ((Ficha)o2).getName();
return n1.compareTo(n2);
}
and then inside an ActionPerformed event I have this:
----------------IN THE ACTION EVENT BUTTON----------------------------
Collections.sort( list , new SortByName() );
"package.SortByName is abstract,> cannot be instantiated"
I tried changing the "abstract" type in the class definition (SortByName) , but it complies about not overriding the compareTo() method.
thanks for reading.
The method you have to implement is called compare, not compareTo.
Abstract classes cannot be instantiated.
Also, Comparator is generic, so you'd better do the following:
public class SortByName implements Comparator<Ficha>{
public int compareTo(Ficha f1, Ficha f2){
String n1 = f1.getName();
String n2 = f2.getName();
return n1.compareTo(n2);
}
}
Comparator needs to implement compare(), not compareTo() method.
class SortByName implements Comparator<Ficha>{
#Override
public int compare(Ficha o1, Ficha o2) {
String n1 = o1.getName();
String n2 = o2.getName();
return n1.compareTo(n2);
}
}
You need to remove "abstract" and implement the equals method as well.
Code should look like:
package package;
import java.util.*;
public class SortByName implements Comparator{
public int compare(Object o1, Object o2){
String n1 = ((Ficha)o1).getName();
String n2 = ((Ficha)o2).getName();
return n1.compareTo(n2);
}
public boolean equals(Object o1) {
// code which compares the current comparator (!) with the object given
}
Note that you might need to use specialized comparators if compiling against a version of java which supports generics. Not sure if this is correct but I think you can do something like:
public class SortByName implements Comparator <Ficha> {
public int compare(Ficha o1, Ficha o2){
// comparing code here
}
}
But again, not entirely sure on that part, you need to test it a bit.
If you check out the Comparator API that will explain how you must implement equals.
Also note that the Comparator interface defines compare, not compareTo.
Laura you were right I had to add the equals method.( u missed the return value)
also remove "abstract" at class definition.
and change compareTo() with compare().
thanks a lot Laura, PROBLEM SOLVED !!!!

Categories