如何确定List是否按Java排序?

时间:2010-06-15 16:23:29

标签: java generics sorting wildcard

我想要一个方法,List<T> T实现Comparable并返回truefalse,具体取决于列表是否已排序

在Java中实现此功能的最佳方法是什么?显而易见的是,泛型和通配符意味着能够轻松处理这些事情,但我总是纠缠不清。

使用类似方法检查列表是否按相反顺序也是很好的。

14 个答案:

答案 0 :(得分:99)

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大部分都已过时(如课程documentation中所述)。

答案 1 :(得分:25)

这是一个通用方法,可以解决这个问题:

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

答案 2 :(得分:16)

易:

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;

包含空值的列表的实现失败。在这种情况下,您必须添加适当的检查。

答案 3 :(得分:11)

如果您使用的是Java 8,则流可能会有所帮助。

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

此代码将对列表进行排序,并将其元素收集到另一个列表中,然后将其与初始列表进行比较。如果两个列表在相同位置包含相同的元素,则比较将成功。

此方法可能不是性能最快的解决方案,但它是最容易实现的方法,不涉及第三方框架。

答案 4 :(得分:5)

检查列表或任何数据结构是否只需要O(n)时间。只需使用Iterator接口遍历列表并从头到尾运行数据(在您的情况下,您已经准备好它作为可比较类型),您可以找到它是否已排序

答案 5 :(得分:3)

只需使用迭代器查看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;
}

答案 6 :(得分: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;
}

答案 7 :(得分:2)

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不确定你们这些人在做什么,但这可以通过简单的循环来完成。

答案 8 :(得分:2)

如果您需要进行单元测试,可以使用AssertJ。它包含一个断言,用于检查List是否已排序:

isSortedAccordingTo

还有一种替代方法{{1}},如果您想使用自定义比较器进行排序,它会使用比较器。

答案 9 :(得分:1)

这是一个需要O(n)时间(最坏情况)的操作。您将需要处理两种情况:列表按降序排序,列表按升序排序。

您需要将每个元素与下一个元素进行比较,同时确保保留订单。

答案 10 :(得分:0)

数组上的一个简单实现:

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

答案 11 :(得分:0)

这是使用IterableComparator的方法。

<T> boolean isSorted(Iterable<? extends T> iterable,
                     Comparator<? super T> comparator) {
    T previous = null;
    for (final T current : iterable) {
        if (previous != null && 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());
}

答案 12 :(得分:0)

使用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)的列表有效。

答案 13 :(得分:0)

IMO,从我所看到的,检查这个的复杂性和第二次执行排序一样糟糕,我知道如果没有排序,人们会短路返回,但如果列表实际上是排序,然后整个长度将被遍历...,我认为只是让代码继续,就像列表被排序一样,让代码本身确定它是否是。

我建议放置一个错误,详细说明为什么会失败的特定行会这样做,因为它的集合没有反转/排序等...

例如

detachTailIndex.run() 将给出 NullPointerException(),

if (fromReversedMethod && detachTailIndex == null) {
throw new NullPointerException("detachTailIndex was null. \n 
Reason: The List<> is required to be reversed before submission")
}

或者,如果您的计划是在排序时使用条件,则您可以使用 null 来验证它是否已排序并选择其他选项。

如果没有其他选项,则使用其他响应即可。

这是另一个例子:

    int key = entry.getKey();
    
    List<Integer> shouldBeReversed = entry.getValue();

    try {
        //If all entries need to be iterated better place them inside the Try-Catch
            updateBatch(key,
                    xes -> {
                        for (int rowIndex : shouldBeReversed
                        ) {
                            xes.remove((int) rowIndex); // will return an IndexOutOfBoundsException if not sorted in reverse
                        }
                        return xes;
                    }
            );
    } catch (IndexOutOfBoundsException e) {
        throw new IndexOutOfBoundsException(e.getMessage() + "\n" +
                "Reason: Batch indexes (Entry's value \"List<Integer>\") should be sorted in reverse order before submission");
    }

如果需要条件(已排序或未排序),则 catch() 正文可用作“未排序”选项。

当然,这是非常非常具体的案例,但似乎为了获得布尔值而检查排序顺序似乎太多(?),特别是在迭代中。