应用条件逻辑获取 Java 列表中最早的 n 个元素
Getting oldest n elements of a Java list with conditional logic applied
Java 8. 我有一个小部件列表 (List<Widget>
),其中一个小部件如下所示:
public class Widget {
// lots of fields
private Date createTime;
// getters, setters & ctors
}
所有 createTime
值都将是过去; none 以后。而现在并不真正存在。 ;-)
我无法控制小部件列表的创建方式或创建数量。但是小部件列表可能很大,所以我需要使用这个小部件列表来确定要删除哪些小部件 (deleteList
)。但是,我需要将一些 Stream API filters/magic 应用于此列表,以便我结束:
- 如果小部件的数量 (
numWidgets
) 小于或等于我要保留的数量 (retentionSize
),那么我想保留所有小部件,所以我想要我的deleteList
为空
- else,
numWidgets > retentionSize
,所以我希望我的 deleteList
只包含 oldest numWidgets - retentionSize
(我将提供一个示例下)
同样这里的算法是:
if numWidgets > retentionSize
i want oldest (numWidgets - retentionSize)
if numWidgets <= retentionSize
i want an empty list
示例:
numWidgets
是83,retentionSize
是90;因为 numWidgets <= retentionSize
那么 deleteList
是空的
numWidgets
是107,retentionSize
是90;因为 numWidgets > retentionSize
那么 deleteList
是列表中 最旧的 numWidgets - retentionSize
(107 - 90 = 17) 个小部件
到目前为止,我使用 Stream API 的最佳尝试是:
// again I don't control how I get allWidgets
List<Widget> allWidgets = getSomehow();
int numWidgets = allWidgets.size();
List<Widget> oldest = (numWidgets > retentionSize)
? allWidgets.sort(Comparator.comparing(widget -> widget.getCreateTime()))
: Collections.emptyList();
这次尝试的几个问题:
- 这是一个编译器错误,因为
allWidgets.sort(...)
不是 return 列表;但即使它做到了...
- 这按时间升序对小部件进行排序,而我相信我想要降序
- 它没有考虑差异 (
numWidgets - retentionSize
)
谁能帮我冲过终点线?
使用skip(long n)
操作:
List<Integer> allWidgets = List.of(1,2,3,4,5,6);
int retentionSize = 2;
List<Integer> result = allWidgets.stream().skip(retentionSize).collect(Collectors.toList());
System.out.println(result);
或者您可以使用 limit(long maxSize)
,具体取决于您对列表的排序方式。
首先,您应该对流进行排序,而不是对列表进行排序。第一个元素应该是最新的。
然后是 skip
第一个 retentionSize
个小部件。您跳过的元素多于流中的元素并不重要。 skip
不在乎。现在,只有最旧的 (numWidgets - retentionSize
) 小部件保留在流中。
List<Widget> allWidgets = getSomehow();
List<Widget> deleteList = allWidgets.stream()
.sorted(Comparator.comparing(Widget::getCreateTime).reversed())
.skip(retentionSize)
.collect(Collectors.toList());
这每次都会对列表进行排序,即使 retentionSize
大于小部件的数量。如果这导致了性能问题,您可以为此添加一个显式检查:
List<Widget> deleteList;
if (numWidgets > retentionSize) {
deleteList = allWidgets.stream()
.sorted(Comparator.comparing(Widget::getCreateTime).reversed())
.skip(retentionSize)
.collect(Collectors.toList());
} else {
deleteList = List.of();
}
如果您想要所有 但 deleteList
中的元素(就像您已删除它们一样),请使用 limit
:
List<Widget> allWidgets = getSomehow();
List<Widget> thingsNotInDeleteList = allWidgets.stream()
.sorted(Comparator.comparing(Widget::getCreateTime).reversed())
.limit(retentionSize)
.collect(Collectors.toList());
Widget
s必须根据createTime
[=17=按自然顺序排序]
最旧的小部件排在第一位
List<Widget> deleteList = (numWidgets > retentionSize)
? allWidgets.stream()
.sorted((w1, w2) -> w1.getCreateTime().compareTo(w2.getCreateTime()))
.limit(numWidgets - retentionSize).collect(toList())
: Collections.emptyList();
试试这个:
List<Widget> deleteList = getSomehow().stream()
.sorted(comparing(Widget::getCreateTime))
.skip(retentionSize)
.collect(toList());
如果您想立即删除所有那些最旧的小部件或执行其他操作,那么您可以使用 forEach
而不是 collect
:
getSomehow().stream()
.sorted(comparing(Widget::getCreateTime))
.skip(retentionSize)
.forEach(w -> /* do something here */);
Java 8. 我有一个小部件列表 (List<Widget>
),其中一个小部件如下所示:
public class Widget {
// lots of fields
private Date createTime;
// getters, setters & ctors
}
所有 createTime
值都将是过去; none 以后。而现在并不真正存在。 ;-)
我无法控制小部件列表的创建方式或创建数量。但是小部件列表可能很大,所以我需要使用这个小部件列表来确定要删除哪些小部件 (deleteList
)。但是,我需要将一些 Stream API filters/magic 应用于此列表,以便我结束:
- 如果小部件的数量 (
numWidgets
) 小于或等于我要保留的数量 (retentionSize
),那么我想保留所有小部件,所以我想要我的deleteList
为空 - else,
numWidgets > retentionSize
,所以我希望我的deleteList
只包含 oldestnumWidgets - retentionSize
(我将提供一个示例下)
同样这里的算法是:
if numWidgets > retentionSize
i want oldest (numWidgets - retentionSize)
if numWidgets <= retentionSize
i want an empty list
示例:
numWidgets
是83,retentionSize
是90;因为numWidgets <= retentionSize
那么deleteList
是空的numWidgets
是107,retentionSize
是90;因为numWidgets > retentionSize
那么deleteList
是列表中 最旧的numWidgets - retentionSize
(107 - 90 = 17) 个小部件
到目前为止,我使用 Stream API 的最佳尝试是:
// again I don't control how I get allWidgets
List<Widget> allWidgets = getSomehow();
int numWidgets = allWidgets.size();
List<Widget> oldest = (numWidgets > retentionSize)
? allWidgets.sort(Comparator.comparing(widget -> widget.getCreateTime()))
: Collections.emptyList();
这次尝试的几个问题:
- 这是一个编译器错误,因为
allWidgets.sort(...)
不是 return 列表;但即使它做到了... - 这按时间升序对小部件进行排序,而我相信我想要降序
- 它没有考虑差异 (
numWidgets - retentionSize
)
谁能帮我冲过终点线?
使用skip(long n)
操作:
List<Integer> allWidgets = List.of(1,2,3,4,5,6);
int retentionSize = 2;
List<Integer> result = allWidgets.stream().skip(retentionSize).collect(Collectors.toList());
System.out.println(result);
或者您可以使用 limit(long maxSize)
,具体取决于您对列表的排序方式。
首先,您应该对流进行排序,而不是对列表进行排序。第一个元素应该是最新的。
然后是 skip
第一个 retentionSize
个小部件。您跳过的元素多于流中的元素并不重要。 skip
不在乎。现在,只有最旧的 (numWidgets - retentionSize
) 小部件保留在流中。
List<Widget> allWidgets = getSomehow();
List<Widget> deleteList = allWidgets.stream()
.sorted(Comparator.comparing(Widget::getCreateTime).reversed())
.skip(retentionSize)
.collect(Collectors.toList());
这每次都会对列表进行排序,即使 retentionSize
大于小部件的数量。如果这导致了性能问题,您可以为此添加一个显式检查:
List<Widget> deleteList;
if (numWidgets > retentionSize) {
deleteList = allWidgets.stream()
.sorted(Comparator.comparing(Widget::getCreateTime).reversed())
.skip(retentionSize)
.collect(Collectors.toList());
} else {
deleteList = List.of();
}
如果您想要所有 但 deleteList
中的元素(就像您已删除它们一样),请使用 limit
:
List<Widget> allWidgets = getSomehow();
List<Widget> thingsNotInDeleteList = allWidgets.stream()
.sorted(Comparator.comparing(Widget::getCreateTime).reversed())
.limit(retentionSize)
.collect(Collectors.toList());
Widget
s必须根据createTime
[=17=按自然顺序排序]
最旧的小部件排在第一位
List<Widget> deleteList = (numWidgets > retentionSize)
? allWidgets.stream()
.sorted((w1, w2) -> w1.getCreateTime().compareTo(w2.getCreateTime()))
.limit(numWidgets - retentionSize).collect(toList())
: Collections.emptyList();
试试这个:
List<Widget> deleteList = getSomehow().stream()
.sorted(comparing(Widget::getCreateTime))
.skip(retentionSize)
.collect(toList());
如果您想立即删除所有那些最旧的小部件或执行其他操作,那么您可以使用 forEach
而不是 collect
:
getSomehow().stream()
.sorted(comparing(Widget::getCreateTime))
.skip(retentionSize)
.forEach(w -> /* do something here */);