List<Date> dates = Arrays.asList( new Date( 2L ), new Date( 3L ) );
boolean isSorted = new ArrayList<>( new TreeSet<>( dates ) ).equals( dates );
List<Date> dates = Arrays.asList( new Date( 2L ), new Date( 3L ) );
boolean isSorted = new ArrayList<>( new TreeSet<>( dates ) ).equals( dates );
Hm. Besser wäre:
boolean isSorted = com.google.common.collect.Ordering.natural().isOrdered(dates);
Dieses Snippet ist nicht sehr … schön.
1. Benutzt man ein Set. Was wenn man auch doppelte Elemente in seiner Liste hat?
2. Wird bei dem Snippet eine neue Collection erzeugt, dann wird diese in eine ArrayList konvertiert, die wieder rum ein neues Array erzeugt.
Sehr ineffizient. Es geht besser! Eine Möglichkeit ist der Vorschlag von ufkub, aber es geht noch besser. Wenn man eine Liste von Date Objekten nutzen möchte, dann kann man sich doch eine eigene Schreiben, die zusätzlich über eine Sortierungsmethode verfügt und intern ein sorted Flag verwaltet. Dabei muss man nur beachten, dass die „hinzufügenden“ Methoden das „isSorted“ Flag neu setzen müssen, alles andere wird an eine dahinter liegende List delegiert. Das ist viel effizienter. Hier ein Implementierungsvorschlag:
public final class DateList implements List, Serializable, Cloneable {
private static final long serialVersionUID = -65974214443173951L;
public static DateList asList(Date… dates) {
return new DateList(Arrays.asList(dates));
}
private final List backend;
private boolean sorted;
public DateList(List backend) {
this.backend = backend;
}
public boolean isSorted() {
return sorted;
}
public void sort() {
Collections.sort(backend);
sorted = true;
}
public void sort(Comparator c) {
Collections.sort(backend, c);
sorted = true;
}
// list interface methods
@Override
public boolean equals(Object obj) {
return backend.equals(obj);
}
@Override
public int hashCode() {
return backend.hashCode();
}
@Override
public String toString() {
return backend.toString();
}
@Override
public DateList clone() {
return new DateList(new ArrayList(backend));
}
@Override
public int size() {
return backend.size();
}
@Override
public boolean isEmpty() {
return backend.isEmpty();
}
@Override
public boolean contains(Object o) {
return backend.contains(o);
}
@Override
public Iterator iterator() {
return listIterator();
}
@Override
public Object[] toArray() {
return backend.toArray();
}
@Override
public T[] toArray(T[] a) {
return backend.toArray(a);
}
@Override
public boolean add(Date e) {
add(size(), e);
return true;
}
@Override
public boolean remove(Object o) {
return backend.remove(o);
}
@Override
public boolean containsAll(Collection c) {
return backend.containsAll(c);
}
@Override
public boolean addAll(Collection c) {
return addAll(size(), c);
}
@Override
public boolean addAll(int index, Collection c) {
boolean result = backend.addAll(index, c);
sorted = false;
return result;
}
@Override
public boolean removeAll(Collection c) {
return backend.removeAll(c);
}
@Override
public boolean retainAll(Collection c) {
return backend.retainAll(c);
}
@Override
public void clear() {
backend.clear();
sorted = false;
}
@Override
public Date get(int index) {
return backend.get(index);
}
@Override
public Date set(int index, Date element) {
Date old = backend.set(index, element);
sorted = false;
return old;
}
@Override
public void add(int index, Date element) {
backend.add(index, element);
sorted = false;
}
@Override
public Date remove(int index) {
return backend.remove(index);
}
@Override
public int indexOf(Object o) {
return backend.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return backend.lastIndexOf(o);
}
@Override
public ListIterator listIterator() {
return listIterator(0);
}
@Override
public ListIterator listIterator(int index) {
return backend.listIterator(index);
}
@Override
public List subList(int fromIndex, int toIndex) {
return new DateList(backend.subList(fromIndex, toIndex));
}
}
Argh, die ganzen spitzen Klammern sind weg. -.- Bitte einfach dazu denken. 😀
Argh Nr. 2: Habe vergessen bei den „remove“ methoden das „sorted“ flag zu setzen, falls die Liste leer wird. Eine leere Liste ist natürlich nicht sortiert. Aber das kann man ja in Handarbeit selbst ergänzen. 🙂
Argh Nr. 3: die „listIterator(int)“ Methode müsste eigentlich eine eigene Implementierung zurück geben, da die remove(), set(Date) und add(Date) Methoden des ListIterators überschrieben werden müssen. Also:
private void checkEmptynessAndSetFlag() {
if (isEmpty()) {
sorted = false;
}
}
@Override
public ListIterator listIterator(final int index) {
return new ListIterator() {
private final ListIterator iteratorBackend = backend.listIterator(index);
@Override
public boolean hasNext() {
return iteratorBackend.hasNext();
}
@Override
public Date next() {
return iteratorBackend.next();
}
@Override
public boolean hasPrevious() {
return iteratorBackend.hasPrevious();
}
@Override
public Date previous() {
return iteratorBackend.previous();
}
@Override
public int nextIndex() {
return iteratorBackend.nextIndex();
}
@Override
public int previousIndex() {
return iteratorBackend.previousIndex();
}
@Override
public void remove() {
iteratorBackend.remove();
checkEmptynessAndSetFlag();
}
@Override
public void set(Date e) {
iteratorBackend.set(e);
sorted = false;
}
@Override
public void add(Date e) {
iteratorBackend.add(e);
sorted = false;
}
};
}