これは機能するかもしれませんが、ベストプラクティスにはほど遠いです。
SortedSetドキュメントから:
ソートされたセットがSetインターフェースを正しく実装するためには、ソートされたセットによって維持される順序(明示的なコンパレーターが提供されているかどうかに関係なく)はequalsと一致している必要があることに注意してください。(equalsとの整合性の正確な定義については、ComparableインターフェイスまたはComparatorインターフェイスを参照してください。)これは、Setインターフェイスがequals操作で定義されているが、並べ替えられたセットがcompareTo(またはcompare)メソッドを使用してすべての要素の比較を実行するためです。したがって、この方法で等しいと見なされる2つの要素は、ソートされたセットの観点からは等しいです。ソートされたセットの動作は、その順序がequalsと矛盾している場合でも明確に定義されています。Setインターフェースの一般的な契約に従わないだけです。
を実装するオブジェクトの場合、メソッドとのComparable
間には常に一貫性が必要です。equals()
hashcode()
compareTo()
恐れ入りますが、 aSortedSet
はあなたが望むものではなく、GuavaMultiSet
も適切ではありません(複数の等しいアイテムを個別に取得できないため)。必要なのはSortedList
。私が知っているような獣はありません(おそらくcommons-collectionsにありますが、それらは少しレガシー側にあります)。そこで、GuavaのForwardingListを基本クラスとして使用して実装しました。つまり、このリストはほとんどすべてをArrayList
内部で使用するリストに委任しますが、そのメソッドで正しい挿入位置を見つけるために使用Collections.binarySearch()
し、指定された位置に値を追加または設定するインターフェイスのすべてのオプションのメソッドにをスローadd()
します。UnsupportedOperationException
List
ListIterator
コンストラクターはのコンストラクターと同じですArrayList
が、それぞれにカスタムの2番目のバージョンもありますComparator
。カスタムコンパレータを使用しない場合は、リスト要素を実装する必要があります。そうしないと、Comparable
並べRuntimeException
替え中にsが発生します。
public class SortedArrayList<E> extends ForwardingList<E> implements
RandomAccess{
private final class ListIteratorImpl extends ForwardingListIterator<E>{
private final int start;
public ListIteratorImpl(final int start){
this.start = start;
}
@Override
public void set(E element){throw new UnsupportedOperationException();}
@Override
public void add(E element){throw new UnsupportedOperationException();}
@Override
protected ListIterator<E> delegate(){return inner.listIterator(start);};
}
private Comparator<? super E> comparator;
private List<E> inner;
public SortedArrayList(){this(null, null, null);}
@SuppressWarnings("unchecked")
private SortedArrayList(
final List<E> existing,
final Collection<? extends E> values,
final Comparator<? super E> comparator
){
this.comparator =
(Comparator<? super E>)
(comparator == null
? Ordering.natural()
: comparator );
inner = (
existing == null
? (values == null
? new ArrayList<E>(values)
: new ArrayList<E>()
)
: existing;
}
public SortedArrayList(final Collection<? extends E> c){
this(null, c, null);
}
public SortedArrayList(final Collection<? extends E> c,
final Comparator<? super E> comparator){
this(null, c, comparator);
}
public SortedArrayList(final Comparator<? super E> comparator){
this(null, null, comparator);
}
public SortedArrayList(final int initialCapacity){
this(new ArrayList<E>(initialCapacity), null, null);
}
public SortedArrayList(final int initialCapacity,
final Comparator<? super E> comparator){
this(new ArrayList<E>(initialCapacity), null, comparator);
}
@Override
public boolean add(final E e){
inner.add(
Math.abs(
Collections.binarySearch(inner, e, comparator)
) + 1,
e
);
return true;
}
@Override
public void add(int i, E e){throw new UnsupportedOperationException();}
@Override
public boolean addAll(final Collection<? extends E> collection){
return standardAddAll(collection);
}
@Override
public boolean addAll(int i,
Collection<? extends E> es){
throw new UnsupportedOperationException();
}
@Override
protected List<E> delegate(){ return inner; }
@Override
public List<E> subList(final int fromIndex, final int toIndex){
return new SortedArrayList<E>(
inner.subList(fromIndex, toIndex),
null,
comparator
);
}
@Override
public ListIterator<E> listIterator(){ return new ListIteratorImpl(0); }
@Override
public ListIterator<E> listIterator(final int index){
return new ListIteratorImpl(index);
}
@Override
public E set(int i, E e){ throw new UnsupportedOperationException(); }
}