Java流:按先前的映射结果进行分组和排序?

Bev*_*vor 2 java lambda java-8 java-stream

我必须遵循以下代码:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class TimeZonesExample
{
    public static void main(String[] args)
    {
        Set<String> allZones = ZoneId.getAvailableZoneIds();
        LocalDateTime localDateTime = LocalDateTime.now();

        List<String> zoneList = new ArrayList<>(allZones);

        for (String s : zoneList)
        {
            ZoneId zoneId = ZoneId.of(s);
            ZonedDateTime zoneDateTime = localDateTime.atZone(zoneId);
            ZoneOffset zoneOffset = zoneDateTime.getOffset();
            String out = String.format("%35s %10s%n", zoneId, zoneOffset);

            System.out.printf(out);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这产生了这样一个列表:

                  Asia/Aden     +03:00
             America/Cuiaba     -03:00
                  Etc/GMT+9     -09:00
                  Etc/GMT+8     -08:00
             Africa/Nairobi     +03:00
            America/Marigot     -04:00
                 Asia/Aqtau     +05:00
          Pacific/Kwajalein     +12:00
        America/El_Salvador     -06:00
             Asia/Pontianak     +07:00
               Africa/Cairo     +02:00
          Pacific/Pago_Pago     -11:00
             Africa/Mbabane     +02:00
               Asia/Kuching     +08:00
                               ....
Run Code Online (Sandbox Code Playgroud)

我尝试将其重写为流结果,而不是for循环并更熟悉流API,结果应该按偏移量排序.结果应如下所示:

-09:00 Etc/GMT+9   
-08:00 Etc/GMT+8    
-04:00 America/Marigot     
-03:00 America/Cuiaba
+03:00 Africa/Nairobi     
+03:00 Asia/Aden 
Run Code Online (Sandbox Code Playgroud)

我能够使用下面的表达式打印偏移量(未排序),但是如何在zoneIds上应用它们?我不知何故必须记住以前的zoneId映射结果.

allZones.stream()
    .map(s -> ZoneId.of(s))
    .map(zId -> localDateTime.atZone(zId).getOffset())
    .forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

shm*_*sel 5

你可以从ZoneId后面抓住ZonedDateTime.getZone().试试这个:

ZoneId.getAvailableZoneIds()
        .stream()
        .map(ZoneId::of)
        .map(ZonedDateTime::now)
        .sorted(Comparator.comparing(ZonedDateTime::getOffset).reversed())
        .forEach(zdt -> System.out.println(zdt.getOffset() + "\t" + zdt.getZone()));
Run Code Online (Sandbox Code Playgroud)