3、JAVA8 之 foreach

前提

  在 Java8 中,我们可以通过使用 forEach 的新功能结合 Stream 可以更加方便的对 Map、List、Set等集合进行遍历。

主题

  1. Loop a Map
  2. Loop a List
  3. forEach and Consumer
  4. forEach and Exception handling
  5. forEach vs forEachOrdered

Loop a Map

 原始遍历

for (Map.Entry<String, Integer> entry : map.entrySet()) {
          System.out.println("Key : " + entry.getKey() + ", Value : " + entry.getValue());
}

 Java8 lambda 循环

map.forEach((k, v) -> System.out.println("Key : " + k + ", Value : " + v));

 假如 map 中的 key 或 value 中有 null 值,那我们需要怎么遍历判断

map.forEach(
    (k, v) -> {
        if (k != null){
            System.out.println("Key : " + k + ", Value : " + v);
        }
    }
);

Loop a List

 原始遍历

for (String l : list) {
    System.out.println(l);
}

 Java8 lambda 循环

// lambda
// list.forEach(x -> System.out.println(x));

// method reference
ist.forEach(System.out::println);

 假如 list 中包含 null 值,那我们需要怎么遍历判断

// filter null value
list.stream()
        .filter(Objects::nonNull)
        .forEach(System.out::println);

forEach and Consumer

 方法函数遍历

public static void main(String[] args) {

    List<String> list = Arrays.asList("abc", "java", "python");

    // convert a String to a Hex
    Consumer<String> printTextInHexConsumer = (String x) -> {
        StringBuilder sb = new StringBuilder();
        for (char c : x.toCharArray()) {
            String hex = Integer.toHexString(c);
            sb.append(hex);
        }
        System.out.print(String.format("%n%-10s:%s", x, sb.toString()));
    };

    // pass a Consumer
    list.forEach(printTextInHexConsumer);
}

forEach and Exception handling

 forEach不只是用于打印,这个示例展示了如何使用forEach方法循环对象列表并将其写入文件,并演示如何使用捕获 Exception 方法。

public class ForEachWriteFile {

    public static void main(String[] args) {

        ForEachWriteFile obj = new ForEachWriteFile();
        obj.save(Paths.get("C:\\test"), obj.createDummyFiles());
    }

    public void save(Path path, List<DummyFile> files) {

        if (!Files.isDirectory(path)) {
            throw new IllegalArgumentException("Path must be a directory");
        }

        files.forEach(f -> {
            try {
                int id = f.getId();
                // create a filename
                String fileName = id + ".txt";
                Files.write(path.resolve(fileName), f.getContent().getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

    }

    public List<DummyFile> createDummyFiles() {
        return Arrays.asList(
                new DummyFile(1, "hello"),
                new DummyFile(2, "world"),
                new DummyFile(3, "java"));
    }

    class DummyFile {
        int id;
        String content;

        public DummyFile(int id, String content) {
            this.id = id;
            this.content = content;
        }

        public int getId() {
            return id;
        }

        public String getContent() {
            return content;
        }
    }
}

forEach vs forEachOrdered

 forEach不能保证流的相遇顺序,无论流是顺序的还是并行的。在并行模式下运行时,结果是显而易见的。

Stream<String> s = Stream.of("a", "b", "c", "1", "2", "3");
s.parallel().forEach(x -> System.out.println(x));

 打印结果如下:

1
2
b
c
3
a

 forEachOrdered 保证了流的相遇顺序;因此,它牺牲了并行性的好处。

Stream<String> s = Stream.of("a", "b", "c", "1", "2", "3");
// keep order, it is always a,b,c,1,2,3
s.parallel().forEachOrdered(x -> System.out.println(x));

 

posted @ 2021-04-18 23:06  星火燎原智勇  阅读(1530)  评论(0编辑  收藏  举报