4

我有一个 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>));

不用说它不起作用,所以任何有其他想法的人都会非常感激。

4

5 回答 5

7

您可以使用TreeSet并提供一个比较器

TreeSet<myData> sorted = new TreeSet<>(Comparator.comparing(MyData::expDtTm));
sorted.addAll(dataLocations);

或者如CollectorJavadocs 类中所述,为以下内容创建您自己的收集器TreeSet

Collector<Widget, ?, TreeSet<Widget>> intoSet =
     Collector.of(
         TreeSet::new, 
         TreeSet::add,
         (left, right) -> { left.addAll(right); return left; }
     );
于 2018-07-13T17:37:51.420 回答
3

您的第三次尝试很接近,尽管书面没有编译。该方法Collectors.toCollection采用 aSupplier返回所需的Collection,而不是Collection本身。

如果MyData定义为:

public class MyData {
  private Instant instant;
  public Instant getInstant() { return instant; }
  public void setInstant(Instant instant) { this.instant = instant; }
}

然后,为了将它们收集到SortedSetvia中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其中也将对元素进行排序

也就是说,在某些情况下 usingStream.sorted是有益的:当Stream.collect返回Collection保证插入顺序的 a 时。ALinkedHashSet以及 , 的任何实现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不能以无序特征。和Collector返回的 s就是这种情况。使用时并非如此Collectors.toCollectionCollectors.toListCollectors.toSet

于 2018-07-13T19:04:09.913 回答
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]
于 2018-07-13T17:41:42.787 回答
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

集合是一个数学集合,它可能只包含每个元素一次。A SortedSetlike aTreeSet使用它的比较器(或者如果没有提供比较器,则使用元素的自然排序)来决定两个元素是否相等,因此不能都在集合中。因此,为了按 对元素进行排序Instant并且仍然保持元素相同Instant,我们需要以其他方式区分它们。所以在我的比较器中,我添加了按批号排序。之后Instant。如果很多没有。也不是唯一的,您将需要添加更多要排序的属性列表。

于 2018-07-17T10:01:09.610 回答
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
于 2018-07-16T14:01:41.377 回答