我有一个Java Set
,可以向其提供信息:
Set<myData> dataLocations = getData(location);
我想对这个Set进行排序,但是我尝试了sortedSet却无法使其正常工作,所以我尝试了这个
dataLocations = dataLocations.stream().sorted(Comparator.comparing(myData -> myData.expDtTm)).collect(Collectors.toSet());
唯一的问题是,在Java文档中,它不能保证保留任何顺序。所以我尝试了这个:
TreeSet<myData> sortedDataLocations = dataLocations.stream().sorted(Comparator.comparing(myData -> myData.expDtTm)).collect(Collectors.toCollection(TreeSet<myData>));
不用说它不起作用,因此任何有其他想法的人都会受到赞赏。
答案 0 :(得分:5)
您可以使用TreeSet
并提供比较器
TreeSet<myData> sorted = new TreeSet<>(Comparator.comparing(MyData::expDtTm));
sorted.addAll(dataLocations);
或者如Collector
类Javadocs中所述,为TreeSet
创建自己的收集器:
Collector<Widget, ?, TreeSet<Widget>> intoSet =
Collector.of(
TreeSet::new,
TreeSet::add,
(left, right) -> { left.addAll(right); return left; }
);
答案 1 :(得分:3)
您的第三次尝试已接近完成,尽管编写时未编译。方法Collectors.toCollection
使用Supplier
来返回所需的Collection
,而不是Collection
本身。
如果MyData
被定义为:
public class MyData {
private Instant instant;
public Instant getInstant() { return instant; }
public void setInstant(Instant instant) { this.instant = instant; }
}
然后,为了通过SortedSet
将它们收集到Stream
中,您可以执行以下操作:
Comparator<MyData> comparator = Comparator.comparing(MyData::getInstant);
TreeSet<MyData> set = getMyData().stream()
.collect(Collectors.toCollection(() -> new TreeSet<>(comparator));
请注意,我在这里不使用Stream.sorted
。如果您被使用Stream.sorted
,实际上是有害的,因为它会增加不利于最终结果的工作。 Stream
会对元素进行排序,然后开始将它们添加到TreeSet
中,而也将对元素进行排序。
也就是说,在某些情况下,使用Stream.sorted
将是有益的:当Stream.collect
返回保证插入顺序的Collection
时。 LinkedHashSet
以及List
的任何实现均保证插入顺序。因此,您可以这样做:
LinkedHashSet<MyData> set = getMyData().stream()
.sorted(comparator)
.collect(Collectors.toCollection(LinkedHashSet::new));
// Or use a List
List<MyData> list = getMyData().stream()
.distinct() // If you want only unique elements in the end List
.sorted(comparator)
.collect(Collectors.toList());
注意:仅末尾Collection
保证插入顺序是不够的。使用的Collector
不得将unordered作为characteristic。 Collector
和Collectors.toList
返回的Collectors.toCollection
就是这种情况。使用Collectors.toSet
的情况不是。
答案 2 :(得分:1)
您尝试以下操作:
public class Example {
public static void main(String[] args) {
Comparator<String> stringComparator =
Comparator.comparing((String x) -> x);
Supplier<TreeSet<String>> supplier =
() -> new TreeSet<>(stringComparator);
Set<String> set = new HashSet<>(Arrays.asList("1", "3", "7", "2", "9", "4"));
TreeSet<String> treeSet = set.stream()
.collect(Collectors.toCollection(supplier));
System.out.println(treeSet);
}
}
将String类替换为您的类。
输出
[1, 2, 3, 4, 7, 9]
答案 3 :(得分:0)
我最终要做的是:
TreeSet<myData> sorted = new TreeSet<>(Comparator.comparing(myData -> myData.ExpDtTm);
现在这不是最佳答案,我仍在寻找另一个答案,因为如果您有2个相同的ExpDtTm,则比较器将删除第二个Instant含义:
| Lot Number | ExpDtTm |
| LOT-4 | 2018-07-16 12:41:56 |
| LOT-7 | 2018-07-16 12:41:56 |
这将导致 LOT-7 被删除而不返回给用户。
NOTE: This is also the time that happens when formatting an Instant to just have a date which I did
for testing purposes
答案 4 :(得分:0)
Comparator<MyData> instantComparator = Comparator
.comparing(MyData::getExpDtTm)
.thenComparing(MyData::getLotNo);
SortedSet<MyData> sorted = new TreeSet<>(instantComparator);
sorted.addAll(dataLocations);
我尝试了以下设置:
LOT-9 2018-07-15T10:39:53Z
LOT-1 2018-07-17T14:46:57Z
LOT-4 2018-07-16T12:41:56Z
LOT-7 2018-07-16T12:41:56Z
排序后变成:
LOT-9 2018-07-15T10:39:53Z
LOT-4 2018-07-16T12:41:56Z
LOT-7 2018-07-16T12:41:56Z
LOT-1 2018-07-17T14:46:57Z
集合是数学集合,每个元素只能包含一次。 SortedSet
之类的TreeSet
使用其比较器(如果没有提供比较器,则使用元素的自然顺序)来确定两个元素是否相等,因此不能同时存在于集合中。因此,为了按Instant
对元素进行排序,并使元素保持相同的Instant
,我们需要以其他方式对其进行区分。因此,在我的比较器中,我添加了按批号排序。在Instant
之后。如果很多。也不是唯一的,您将需要添加其他要排序的属性列表。