Ответ 1
Использовать API sort(List list, Comparator c)
, который указывает компаратор, и реализовать, как вам угодно.
В качестве альтернативы, если вам особо не нужен Список, используйте SortedSet
, то же самое происходит с компаратором.
Предположим, у меня есть пользовательский класс Java с именем Foo, такой как:
public class Foo
{
private String aField;
@Override
public String toString()
{
return aField;
}
}
И коллекция, такая как:
List<Foo> aList;
Я хочу отсортировать список в алфавитном порядке по каждому возвращаемому элементу .toString().
Я пытался использовать метод Collections.sort(), но результат оказался не тем, что я пытался. Что мне нужно сделать, чтобы сделать это?
Использовать API sort(List list, Comparator c)
, который указывает компаратор, и реализовать, как вам угодно.
В качестве альтернативы, если вам особо не нужен Список, используйте SortedSet
, то же самое происходит с компаратором.
Collections.sort(fooList,
new Comparator<Foo>()
{
public int compare(Foo f1, Foo f2)
{
return f1.toString().compareTo(f2.toString());
}
});
Предполагая, что toString никогда не возвращает null и что в списке нет нулевых элементов.
google-collections делает это очень легко с Ordering:
Collections.sort(list, Ordering.usingToString());
Является ли создание целой сторонней библиотеки просто для использования чего-то, что вы могли бы написать тривиально с помощью компаратора (как это было предусмотрено другими)? Нет, но google-коллекции настолько классные, что вы захотите иметь его в любом случае по целому ряду причин.
На фронте сортировки вы также можете легко делать такие вещи, как реверсирование:
Ordering.usingToString().reverse();
или разрыв связей:
Ordering.usingToString().compound(someOtherComparator);
или иметь дело с нулями:
Ordering.usingToString().nullsFirst();
и т.д., но там есть куча больше материала (конечно, не связанного с сортировкой), что приводит к действительно выразительному коду. Проверьте это!
public class Foo
implements Comparable<Foo>
{
private String aField;
public Foo(String s)
{
aField=s;
}
public String getAField()
{
return aField;
}
public int compareTo(Foo other)
{
return getAField().compareTo(other.getAField());
}
@Override
public String toString()
{
return getAField();
}
}
а затем
Collections.sort(список);
Я бы сделал что-то очень похожее на Пьера:
public class Foo implements Comparable<Foo>
{
private String aField;
@Override
public String toString()
{
return aField;
}
public int compareTo(Foo o)
{
return this.toString().compareTo(o.toString());
}
}
Затем, как и Пьер, я использовал бы Collections.sort(list)
, как предлагает Пьер.
Я бы настоятельно советовал вам использовать toString только для целей отладки... однако... расширить то, что написал Yuval A выше...
public class X implements Comparator { public int compare(final Foo a, final Foo b) { return (a.toString().compareTo(b.toString())); } }
Однако вам действительно нужно, чтобы Foo реализовал Comarable или написал правильный Compartor, который не использует toString.
lambdaj позволяет сортировать, фильтровать и в целом управлять коллекциями без написания циклов или скрытых внутренних классов. Например, сортировка, которую вы задавали, может быть достигнута, как следует из:
sort(foos, on(Foo.class).toString());
Если вы заинтересованы в этом, проверьте его:
Версия Java 8:
list.sort(Comparator.comparing(Object::toString));
Или потоковая передача:
List<Foo> sortedList = unsortedList
.stream()
.sorted(Comparator.comparing(Object::toString)))
.collect(Collectors.toList());
Если вы хотите, чтобы сбор оставался отсортированным, а не сортировал его в определенных точках, вы могли бы поместить его в TreeSet с определенным Comparator. В противном случае я бы использовал метод Collections.sort, уже упомянутый Yuval.