Java 8 forEach examples
In Java 8, we can use the new forEach
to loop or iterate a Map
, List
, Set
, or Stream
.
Topics
- Loop a Map
- Loop a List
- forEach and Consumer
- forEach and Exception handling
- forEach vs forEachOrdered
1. Loop a Map
1.1 Below is a normal way to loop a Map
.
public static void loopMapClassic() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 10);
map.put("B", 20);
map.put("C", 30);
map.put("D", 40);
map.put("E", 50);
map.put("F", 60);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println("Key : " + entry.getKey() + ", Value : " + entry.getValue());
}
}
1.2 In Java 8, we can use forEach
to loop a Map
and print out its entries.
public static void loopMapJava8() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 10);
map.put("B", 20);
map.put("C", 30);
map.put("D", 40);
map.put("E", 50);
map.put("F", 60);
// lambda
map.forEach((k, v) -> System.out.println("Key : " + k + ", Value : " + v));
}
Output
Key : A, Value : 10
Key : B, Value : 20
Key : C, Value : 30
Key : D, Value : 40
Key : E, Value : 50
Key : F, Value : 60
1.3 For the Map
‘s key or value containing null
, the forEach
will print null
.
public static void loopMapJava8() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 10);
map.put("B", 20);
map.put("C", 30);
map.put(null, 40);
map.put("E", null);
map.put("F", 60);
// ensure map is not null
if (map != null) {
map.forEach((k, v) -> System.out.println("Key : " + k + ", Value : " + v));
}
}
Output
Key : null, Value : 40
Key : A, Value : 10
Key : B, Value : 20
Key : C, Value : 30
Key : E, Value : null
Key : F, Value : 60
P.S The normal way to loop a Map
will print the same above output.
1.4 If we do not want to print the null
key, add a simple null checking inside the forEach
.
public static void loopMapJava8() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 10);
map.put("B", 20);
map.put("C", 30);
map.put(null, 40);
map.put("E", null);
map.put("F", 60);
map.forEach(
(k, v) -> {
// yes, we can put logic here
if (k != null){
System.out.println("Key : " + k + ", Value : " + v);
}
}
);
}
Output
Key : A, Value : 10
Key : B, Value : 20
Key : C, Value : 30
Key : E, Value : null
Key : F, Value : 60
2. Loop a List
2.1 Below is a normal way to loop a List
.
public static void loopListClassic() {
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
// normal loop
for (String l : list) {
System.out.println(l);
}
}
2.2 Java 8 forEach
to loop a List
.
public static void loopListJava8() {
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
// lambda
// list.forEach(x -> System.out.println(x));
// method reference
list.forEach(System.out::println);
}
Output
A
B
C
D
E
2.3 This example filters the null value of a List
.
public static void loopListJava8() {
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add(null);
list.add("D");
list.add("E");
// filter null value
list.stream()
.filter(Objects::nonNull)
.forEach(System.out::println);
}
Output
A
B
D
E
P.S The forEach
for Set
and Stream
works the same way.
3. forEach and Consumer
3.1 Review the forEach
method signature, it accepts a functional interface Consumer.
public interface Iterable<T> {
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
//..
}
public interface Stream<T> extends BaseStream<T, Stream<T>> {
void forEach(Consumer<? super T> action);
//...
}
3.2 This example creates a Consumer
method to print String to its Hex format. We can now reuse the same Consumer
method and pass it to the forEach
method of List
and Stream
.
package com.mkyong.java8.misc;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class ForEachConsumer {
public static void main(String[] args) {
List<String> list = Arrays.asList("abc", "java", "python");
Stream<String> stream = Stream.of("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);
stream.forEach(printTextInHexConsumer);
}
}
Output
abc :616263
java :6a617661
python :707974686f6e
abc :616263
java :6a617661
python :707974686f6e
4. forEach and Exception handling.
4.1 The forEach
is not just for printing, and this example shows how to use forEach
method to loop a list of objects and write it to files.
package com.mkyong.java8.misc;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
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;
}
}
}
The above program will create three text files.
hello
world
java
4.2 The Files.write
may throws IOException
, and we must catch the exception inside the forEach
; thus, the code looks ugly. The common practice is to extract the code to a new method.
public void save(Path path, List<DummyFile> files) {
if (!Files.isDirectory(path)) {
throw new IllegalArgumentException("Path must be a directory");
}
// extract it to a new method
/*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();
}
});*/
// nice!
files.forEach(f -> saveFile(path, f));
}
public void saveFile(Path path, DummyFile 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();
}
}
Now, we also can write code like this:
ForEachWriteFile obj = new ForEachWriteFile();
Path path = Paths.get("C:\\test");
obj.createDummyFiles().forEach(o -> obj.saveFile(path, o));
5. forEach vs forEachOrdered
5.1 The forEach
does not guarantee the stream’s encounter order, regardless of whether the stream is sequential or parallel. The result is obvious when run in a parallel mode.
Stream<String> s = Stream.of("a", "b", "c", "1", "2", "3");
s.parallel().forEach(x -> System.out.println(x));
Each run will generate different result:
1
2
b
c
3
a
5.2 The forEachOrdered
guarantees the stream’s encounter order; thus, it sacrifices the benefit of parallelism.
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));
The result is always a,b,c,1,2,3
a
b
c
1
2
3
Download Source Code
$ git clone https://github.com/mkyong/core-java
$ cd java8
Hi:
I keep learning a lot from your examples.. they are simple and to the point..thank you and keep it up.
Thanks, I updated the article with more examples.
Good page. Clear and simple examples. Thanks!
The only think I don’t like using forEach is when you want to call inside it a service that throws exceptions, because you must catch them inside forEach loop. It doesn’t happen with “for” sentence, as you can have the try outside it.
Clear and simple examples.
Keep it up!
Thanks for the additional examples. This was the most thorough tutorial I’ve seen, and the only one to address the need for null checks.
and I am always watching your example when I am getting error in my work.
Hi mkyong,
given all examples are simple and point to point, Thanks a lot.
forEach() is orderd ,while parallel() may not
can you please give me some examples how to replace the items in the list using Stream().
Hi Mkyong,
I really inspired by your way of explanation, very simple to understand.
Great examples. Thanks.
It really helped me.. thank you so much
Thanks, I was iterating a forEeah loop and instead of sysout. I want to perform few operations but I was getting an error. Your post help me identify what should I do.
hello, thanks for this tutorial. In Java 8 possible to use ‘::’ ?
items.forEach(System.out::println);
yes, method reference
https://mkyong.com/java8/java-8-method-references-double-colon-operator/
I checked it. It is equals the– items.forEach(item->System.out.println(item)); –?
Because the parameter and the return type is the same?
Sorry for dump question .
When I do this, I am getting a null pointer exception when the value in the map is null (v is null). How can I avoid that?
items.forEach((k,v)->System.out.println(“Item : ” + k + ” Count : ” + v));
Optional.ofNullable(items).orElse(Collections.emptyMap())
.forEach((k, v) -> System.out.println(“Item : ” + k + ” Count : ” + v));
The
Optional.ofNullable(items).orElse(Collections.emptyMap())
is good for return type.For this case, a simple
if(items!=)
is sufficient.if (items != null) items.forEach((k,v)->System.out.println(“Item : ” + k + ” Count : ” + v));