web-dev-qa-db-ja.com

リストがJavaでソートされているかどうかを判断する方法は?

List<T>を受け取り、TComparableを実装し、リストがソートされているかどうかに応じてtrueまたはfalseを返すメソッドが必要です。

これをJavaで実装する最良の方法は何ですか?ジェネリックとワイルドカードがそのようなことを簡単に処理できることを意図していることは明らかですが、私はすべて混乱しています。

リストが逆順であるかどうかを確認するための類似の方法があるといいでしょう。

55
Eric Wilson

Guava は、素晴らしい Ordering クラスを通じてこの機能を提供します。 OrderingComparator ++です。この場合、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の残りの部分がほとんど廃止されているためです(クラスで説明されているように- ドキュメント )。

103
ColinD

トリックを実行する一般的なメソッドを次に示します。

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;
}
25
Sean

簡単:

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値を含むリストの実装は失敗します。この場合、適切なチェックを追加する必要があります。

16
Daniel

Java 8を使用している場合、ストリームが役立ちます。

list.stream().sorted().collect(Collectors.toList()).equals(list);

このコードは、リストを適切な場所でソートし、その要素を別のリストに収集します。その後、その要素は最初のリストと比較されます。両方のリストに同じ位置に同じ要素が含まれている場合、比較は成功します。

この方法は、最も高速なソリューションではないかもしれませんが、サードパーティのフレームワークを含まない実装が最も簡単な方法です。

13
Palle

リストまたはその問題のデータ構造が、O(n)時間のみを要するタスクであるかどうかを確認します。Iteratorインターフェイスを使用してリストを反復処理し、実行します。最初から最後までのデータ(あなたの場合は、既にComparableのタイプとして準備ができている)で、ソートされているかどうかを簡単に確認できます。

5
bragboy
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ループで行うことができます。

3
digitebs

イテレータを使用して、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;
}
3
jjnguy

単体テストに必要な場合は、 AssertJ を使用できます。リストがソートされているかどうかを確認するアサーションが含まれています。

List<String> someStrings = ...
assertThat(someStrings).isSorted();

ソートにカスタムコンパレータを使用する場合にコンパレータを使用する代替メソッドisSortedAccordingToもあります。

2
Wim Deblauwe

これはO(n)時間(最悪の場合)を要する操作です。リストを降順でソートする場合とリストをソートする場合の2つの場合を処理する必要があります。昇順。

順序が維持されていることを確認しながら、各要素を次の要素と比較する必要があります。

1
Vivin Paliath

これは私がすることです:

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
Yishai

配列の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;
}
0
mikera

IterableComparatorを使用するメソッドがあります。

<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;
}

IterableComparableのメソッドと順序付けのフラグ。

<T extends Comparable<? super T>> boolean isSorted(
        Iterable<? extends T> iterable, boolean natural) {
    return isSorted(iterable, natural ? naturalOrder() : reverseOrder());
}
0
Jin Kwon

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)も実装しているリストに対してのみ効率的です。

0
sakra