如何在读取 java 中的列表时保留 10 个最大整数?
how to keep 10 biggest integer while reading a list in java?
我有一个列表中的整数列表,我想在迭代列表时保留 10 个最大的整数并将它们保存在 TreeSet 中。我正在使用此代码:
for(Integer i : list) {
if (treeSet.size() < 10) {
treeSet.add(i);
} else if (i > treeSet.last()) {
treeSet.pollLast();
treeSet.add(i);
}
}
但是当我在 运行 这段代码之前更改列表中整数的顺序时,结果是不同的。我的代码是真的吗?
treeSet
以升序保存其数据(第一个是最小的),因此您应该替换第一个元素,而不是最后一个:
for(Integer i : list) {
if (treeSet.size() < 10) {
treeSet.add(i);
} else if (i > treeSet.first()) {
treeSet.pollFirst();
treeSet.add(i);
}
}
使用Collection.sort()
and get the desired number of results with List.subList()
.
// Sort the arraylist
Collections.sort(list);
//gets the last 10 item, last is the largest for ascending default sort
list.subList(list.size()-10, list.size());
尝试使用流(如果可以使用 Java 8):
final Comparator<Integer> order = Integer::compare;
List<Integer> collect = list.stream().sorted(order.reversed()).limit(10).sorted().collect(Collectors.toList());
您也可以使用 parallelStream() 而不是 stream() ,后者应该更快。
http://blog.takipi.com/new-parallelism-apis-in-java-8-behind-the-glitz-and-glamour/
Warning: Note that your approach is flawed in general (and this flaw is also present in the originally accepted answer): This may deliver wrong results when there are duplicate elements in the list. A random example where I noticed this is an input list like
List<Integer> list = Arrays.asList(
0, 8, 9, 7, 15, 13, 11, 1, 19, 14,
17, 17, 13, 2, 15, 4, 4, 15, 1, 0);
for which it returns
[1, 7, 8, 9, 11, 13, 14, 15, 17, 19]
instead of
[4, 7, 8, 9, 11, 13, 14, 15, 17, 19]
一个简单直接的解决方案如下:
private static <T> Collection<T> keepLargest(
List<? extends T> list, Comparator<T> comparator, int n)
{
TreeSet<T> treeSet = new TreeSet<T>(comparator);
for(T t : list)
{
treeSet.add(t);
while (treeSet.size() > n)
{
treeSet.pollFirst();
}
}
return treeSet;
}
可以称为
Collection<Integer> kept =
keepLargest(list, Comparator.naturalOrder(), 10);
现在可以争论重复的插入和删除(这是可以避免的),但是由于树集很小,插入的 log(n)
应该可以忽略不计。如果这种性能高度相关,人们也可以考虑使用类似的方法和 PriorityQueue
,或者尝试优化这个解决方案,但在目前的形式下,它非常简单而且不容易出错(过早? ) 优化。
我有一个列表中的整数列表,我想在迭代列表时保留 10 个最大的整数并将它们保存在 TreeSet 中。我正在使用此代码:
for(Integer i : list) {
if (treeSet.size() < 10) {
treeSet.add(i);
} else if (i > treeSet.last()) {
treeSet.pollLast();
treeSet.add(i);
}
}
但是当我在 运行 这段代码之前更改列表中整数的顺序时,结果是不同的。我的代码是真的吗?
treeSet
以升序保存其数据(第一个是最小的),因此您应该替换第一个元素,而不是最后一个:
for(Integer i : list) {
if (treeSet.size() < 10) {
treeSet.add(i);
} else if (i > treeSet.first()) {
treeSet.pollFirst();
treeSet.add(i);
}
}
使用Collection.sort()
and get the desired number of results with List.subList()
.
// Sort the arraylist
Collections.sort(list);
//gets the last 10 item, last is the largest for ascending default sort
list.subList(list.size()-10, list.size());
尝试使用流(如果可以使用 Java 8):
final Comparator<Integer> order = Integer::compare;
List<Integer> collect = list.stream().sorted(order.reversed()).limit(10).sorted().collect(Collectors.toList());
您也可以使用 parallelStream() 而不是 stream() ,后者应该更快。
http://blog.takipi.com/new-parallelism-apis-in-java-8-behind-the-glitz-and-glamour/
Warning: Note that your approach is flawed in general (and this flaw is also present in the originally accepted answer): This may deliver wrong results when there are duplicate elements in the list. A random example where I noticed this is an input list like
List<Integer> list = Arrays.asList( 0, 8, 9, 7, 15, 13, 11, 1, 19, 14, 17, 17, 13, 2, 15, 4, 4, 15, 1, 0);
for which it returns
[1, 7, 8, 9, 11, 13, 14, 15, 17, 19]
instead of
[4, 7, 8, 9, 11, 13, 14, 15, 17, 19]
一个简单直接的解决方案如下:
private static <T> Collection<T> keepLargest(
List<? extends T> list, Comparator<T> comparator, int n)
{
TreeSet<T> treeSet = new TreeSet<T>(comparator);
for(T t : list)
{
treeSet.add(t);
while (treeSet.size() > n)
{
treeSet.pollFirst();
}
}
return treeSet;
}
可以称为
Collection<Integer> kept =
keepLargest(list, Comparator.naturalOrder(), 10);
现在可以争论重复的插入和删除(这是可以避免的),但是由于树集很小,插入的 log(n)
应该可以忽略不计。如果这种性能高度相关,人们也可以考虑使用类似的方法和 PriorityQueue
,或者尝试优化这个解决方案,但在目前的形式下,它非常简单而且不容易出错(过早? ) 优化。