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

时间:2017-01-04 20:24:16

标签: 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);
        }
    }
}

这产生了这样一个列表:

                  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
                               ....

而不是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 

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

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

3 个答案:

答案 0 :(得分: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()));

答案 1 :(得分:3)

您无法返回到流的上一步,以便在当前步骤之前获取该元素。

要对流进行排序,您必须提供一种使用比较器对字符串进行排序的方法。

将代码转换为应用sorted(),这会产生您想要的输出:

allZones.stream()
    .sorted(Comparator.<String, ZoneOffset>comparing(s -> localDateTime.atZone(ZoneId.of(s)).getOffset()).reversed())
    .map(s -> String.format("%10s %s", localDateTime.atZone(ZoneId.of(s)).getOffset(), ZoneId.of(s)))
    .forEach(System.out::println);

答案 2 :(得分:1)

如Piotr所说,您可以使用Stream#sorted对流进行排序。

通过这样做,我得到了类似你的预期输出:

allZones.stream()
    .map(s -> ZoneId.of(s))
    .map(zId -> localDateTime.atZone(zId))
    .sorted((o1, o2) -> o1.getOffset().getTotalSeconds() - o2.getOffset().getTotalSeconds())
    .forEach(ldt -> System.out.format("%35s %10s%n", ldt.getZone(), ldt.getOffset()));