Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering Set by Instant

I have a Java Set that I give information to:

Set<myData> dataLocations = getData(location);

I would like to sort this Set I have tried a sortedSet and couldn't get it to work, so I tried this

dataLocations = dataLocations.stream().sorted(Comparator.comparing(myData -> myData.expDtTm)).collect(Collectors.toSet());

The only problem is that in the Java documentation it doesn't guarantee retaining any orders. So I tried this:

TreeSet<myData> sortedDataLocations = dataLocations.stream().sorted(Comparator.comparing(myData -> myData.expDtTm)).collect(Collectors.toCollection(TreeSet<myData>));

needless to say it didn't work so anyone that has any other ideas they would be much appreciated.

like image 387
TOTOROCATBUS Avatar asked Dec 23 '22 05:12

TOTOROCATBUS


2 Answers

You can use TreeSet and provide a comparator

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

Or as described in Collector class Javadocs create your own collector for TreeSet:

Collector<Widget, ?, TreeSet<Widget>> intoSet =
     Collector.of(
         TreeSet::new, 
         TreeSet::add,
         (left, right) -> { left.addAll(right); return left; }
     );
like image 188
Karol Dowbecki Avatar answered Dec 30 '22 23:12

Karol Dowbecki


Your third attempt was close though as written doesn't compile. The method Collectors.toCollection takes a Supplier that returns the desired Collection, not the Collection itself.

If MyData was defined as:

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

Then in order to collect them into a SortedSet via Streams you could do:

Comparator<MyData> comparator = Comparator.comparing(MyData::getInstant);
TreeSet<MyData> set = getMyData().stream()
            .collect(Collectors.toCollection(() -> new TreeSet<>(comparator));

Note that I don't use Stream.sorted here. It is actually detrimental if you were to use Stream.sorted because it adds work that doesn't help the end result. The Stream would sort its elements and then later start adding them to the TreeSet which will also sort the elements.

That said, there are cases where using Stream.sorted would be beneficial: when Stream.collect returns a Collection that guarantees insertion order. A LinkedHashSet, as well as any implementation of List, guarantee insertion order. So you could do:

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());

Note: It is not enough that the end Collection guarantees insertion order. The Collector being used must not have unordered as a characteristic. This is the case with the Collectors returned by Collectors.toCollection and Collectors.toList. It is not the case when using Collectors.toSet.

like image 25
Slaw Avatar answered Dec 31 '22 01:12

Slaw