我想要一种方法,该方法采用List<T>
whereT
实现Comparable
并返回,true
或者false
取决于列表是否已排序。
用Java实现此的最佳方法是什么?显然,泛型和通配符是为了能够轻松处理此类事情,但我正陷入困境。
如果有一个类似的方法来检查列表是否是相反的顺序,那也很好。
我想要一种方法,该方法采用List<T>
whereT
实现Comparable
并返回,true
或者false
取决于列表是否已排序。
用Java实现此的最佳方法是什么?显然,泛型和通配符是为了能够轻松处理此类事情,但我正陷入困境。
如果有一个类似的方法来检查列表是否是相反的顺序,那也很好。
Answers:
番石榴通过其出色的Ordering类提供了此功能。AnOrdering
是Comparator
++。在这种情况下,如果您具有实现的某种类型的列表Comparable
,则可以编写:
boolean sorted = Ordering.natural().isOrdered(list);
这适用于任何Iterable
,而不仅仅是List
,并且您可以null
通过指定s应该在其他任何非null
元素之前还是之后轻松地处理s :
Ordering.natural().nullsLast().isOrdered(list);
另外,由于您提到您希望能够检查颠倒顺序和正常顺序,因此可以执行以下操作:
Ordering.natural().reverse().isOrdered(list);
Java 8用户:请改用等效的Java语言Comparators#isInOrder(Iterable)
,因为其余的Ordering大多已过时(如类文档中所述)。
isStrictlyOrdered()
如果您想确保没有重复项。
Comparator
吗?我认为这Ordering.from
是出于以下目的:“基于现有的比较器实例返回一个排序。请注意,不必创建一个新的匿名内部类来实现Comparator,只需将其传递到此处即可。相反,只需对Ordering子类化并直接实现其compare方法。”
Ordering.from(comparator).isOrdered(list)
; 但是,如果您要自己实现比较器,则最好只是扩展Ordering
而不是先实现Comparator
,在这种情况下,它就是myOrdering.isOrdered(list)
。
这是可以解决问题的通用方法:
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;
}
如果您使用的是Java 8或更高版本,流可能会有所帮助。
list.stream().sorted().collect(Collectors.toList()).equals(list);
此代码将对列表进行排序,并将其元素收集到另一个列表中,然后将其与初始列表进行比较。如果两个列表在相同位置包含相同元素,则比较将成功。
请注意,此方法将比其他方法具有更差的空间和时间复杂度,因为它将不得不对列表进行排序,因此,不应将其用于非常大的列表。但这是最容易使用的,因为它是单个表达式,并且不涉及第三方库。
简单:
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;
对于包含空值的列表,实现失败。在这种情况下,您必须添加适当的检查。
tmp
没有填充。
要检查列表或任何数据结构是否只需要O(n)时间的任务。只需使用Iterator
Interface遍历列表,然后从头到尾遍历数据(在您的情况下,您已经准备好将其作为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;
}
previous
将永远不会进行设置。请参阅丹尼尔的答案以确保正确流动。
<T extends Comparable>
。
使用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
)。
如果您无权访问流的基础集合,则可以使用以下丑陋的方法:
Stream<T> stream = ...
Comparator<? super T> comparator = ...
boolean isSorted = new AtomicInteger(0) {{
stream.sequential()
.reduce((left, right) -> {
getAndUpdate(order -> (order <= 0) ? comparator.compare(left, right) : order);
return right;
});
}}.get() <= 0;
此操作将花费O(n)时间(最坏的情况)。您将需要处理两种情况:列表以降序排列,列表以升序排列。
您需要将每个元素与下一个元素进行比较,同时确保保留顺序。
这就是我要做的:
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;
}
一个简单的数组实现:
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;
}
List
器具RandomAccess
和使用,如果这样这个实现,一个Iterator
如果没有实现。您实际上并不想按LinkedList
原样使用它。
这是使用anIterable
和a的方法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
ofComparable
和标志的方法。
<T extends Comparable<? super T>> boolean isSorted(
Iterable<? extends T> iterable, boolean natural) {
return isSorted(iterable, natural ? naturalOrder() : reverseOrder());
}