List<T>
を受け取り、T
がComparable
を実装し、リストがソートされているかどうかに応じてtrue
またはfalse
を返すメソッドが必要です。
これをJavaで実装する最良の方法は何ですか?ジェネリックとワイルドカードがそのようなことを簡単に処理できることを意図していることは明らかですが、私はすべて混乱しています。
リストが逆順であるかどうかを確認するための類似の方法があるといいでしょう。
Guava は、素晴らしい Ordering クラスを通じてこの機能を提供します。 Ordering
はComparator
++です。この場合、Comparable
を実装する何らかのタイプのリストがある場合、次のように記述できます。
_boolean sorted = Ordering.natural().isOrdered(list);
_
これはIterable
だけでなくList
でも機能し、null
を他の非null
の前に置くか後に置くかを指定することで簡単に処理できます。要素:
_Ordering.natural().nullsLast().isOrdered(list);
_
また、通常と同様に逆順もチェックできるようにしたいと言ったので、それは次のように行われます:
_Ordering.natural().reverse().isOrdered(list);
_
Java 8ユーザー:代わりに同等のComparators#isInOrder(Iterable)
を使用します。これは、Orderingの残りの部分がほとんど廃止されているためです(クラスで説明されているように- ドキュメント )。
トリックを実行する一般的なメソッドを次に示します。
public static <T extends Comparable<? super T>>
boolean isSorted(Iterable<T> iterable) {
Iterator<T> iter = iterable.iterator();
if (!iter.hasNext()) {
return true;
}
T t = iter.next();
while (iter.hasNext()) {
T t2 = iter.next();
if (t.compareTo(t2) > 0) {
return false;
}
t = t2;
}
return true;
}
簡単:
List tmp = new ArrayList(myList);
Collections.sort(tmp);
boolean sorted = tmp.equals(myList);
または(要素が比較可能な場合):
Object prev;
for( Object elem : myList ) {
if( prev != null && prev.compareTo(elem) > 0 ) {
return false;
}
prev = elem;
}
return true;
または(要素が比較できない場合):
Object prev;
for( Object elem : myList ) {
if( prev != null && myComparator.compare(prev,elem) > 0 ) {
return false;
}
prev = elem;
}
return true;
Null値を含むリストの実装は失敗します。この場合、適切なチェックを追加する必要があります。
Java 8を使用している場合、ストリームが役立ちます。
list.stream().sorted().collect(Collectors.toList()).equals(list);
このコードは、リストを適切な場所でソートし、その要素を別のリストに収集します。その後、その要素は最初のリストと比較されます。両方のリストに同じ位置に同じ要素が含まれている場合、比較は成功します。
この方法は、最も高速なソリューションではないかもしれませんが、サードパーティのフレームワークを含まない実装が最も簡単な方法です。
リストまたはその問題のデータ構造が、O(n)時間のみを要するタスクであるかどうかを確認します。Iterator
インターフェイスを使用してリストを反復処理し、実行します。最初から最後までのデータ(あなたの場合は、既にComparableのタイプとして準備ができている)で、ソートされているかどうかを簡単に確認できます。
private static <T extends Comparable<? super T>> boolean isSorted(List<T> array){
for (int i = 0; i < array.size()-1; i++) {
if(array.get(i).compareTo(array.get(i+1))> 0){
return false;
}
}
return true;
}
zzzzzは皆さんが何をしているのかわかりませんが、これは単純なforループで行うことができます。
イテレータを使用して、List<T>
。
public static <T extends Comparable> boolean isSorted(List<T> listOfT) {
T previous = null;
for (T t: listOfT) {
if (previous != null && t.compareTo(previous) < 0) return false;
previous = t;
}
return true;
}
単体テストに必要な場合は、 AssertJ を使用できます。リストがソートされているかどうかを確認するアサーションが含まれています。
List<String> someStrings = ...
assertThat(someStrings).isSorted();
ソートにカスタムコンパレータを使用する場合にコンパレータを使用する代替メソッドisSortedAccordingTo
もあります。
これはO(n)時間(最悪の場合)を要する操作です。リストを降順でソートする場合とリストをソートする場合の2つの場合を処理する必要があります。昇順。
順序が維持されていることを確認しながら、各要素を次の要素と比較する必要があります。
これは私がすることです:
public static <T extends Comparable<? super T>> boolean isSorted(List<T> list) {
if (list.size() != 0) {
ListIterator<T> it = list.listIterator();
for (T item = it.next(); it.hasNext(); item = it.next()) {
if (it.hasPrevious() && it.previous().compareTo(it.next()) > 0) {
return false;
}
}
}
return true;
}
配列の1つの簡単な実装:
public static <T extends Comparable<? super T>> boolean isSorted(T[] a, int start, int end) {
while (start<end) {
if (a[start].compareTo(a[start+1])>0) return false;
start++;
}
return true;
}
リストの変換:
public static <T extends Comparable<? super T>> boolean isSorted(List<T> a) {
int length=a.size();
if (length<=1) return true;
int i=1;
T previous=a.get(0);
while (i<length) {
T current=a.get(i++);
if (previous.compareTo(current)>0) return false;
previous=current;
}
return true;
}
Iterable
とComparator
を使用するメソッドがあります。
<T> boolean isSorted(Iterable<? extends T> iterable,
Comparator<? super T> comparator) {
boolean beforeFirst = true;
T previous = null;
for (final T current : iterable) {
if (beforeFirst) {
beforeFirst = false;
previous = current;
continue;
}
if (comparator.compare(previous, current) > 0) {
return false;
}
previous = current;
}
return true;
}
Iterable
のComparable
のメソッドと順序付けのフラグ。
<T extends Comparable<? super T>> boolean isSorted(
Iterable<? extends T> iterable, boolean natural) {
return isSorted(iterable, natural ? naturalOrder() : reverseOrder());
}
Java 8ストリームを使用:
boolean isSorted = IntStream.range(1, list.size())
.map(index -> list.get(index - 1).compareTo(list.get(index)))
.allMatch(order -> order <= 0);
これは空のリストでも機能します。ただし、RandomAccess
マーカーインターフェイス(たとえば、ArrayList
)も実装しているリストに対してのみ効率的です。