3、JAVA8 之 foreach
前提
在 Java8 中,我们可以通过使用 forEach 的新功能结合 Stream 可以更加方便的对 Map、List、Set等集合进行遍历。
主题
- Loop a Map
- Loop a List
- forEach and Consumer
- forEach and Exception handling
- 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));