Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

lja9702/java8_tutorial

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

4 Commits

Repository files navigation

Java 8 Tuturial (ko)

https://winterbe.com/posts/2014/03/16/java-8-tutorial/ ๋ฅผ ๋ฒˆ์—ญํ•˜์˜€์Šต๋‹ˆ๋‹ค.

INDEX

Default Methods for Interfaces

Java 8์€ default ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด interface์— non-abstract ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ Extension Methods๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด, Formula์ธํ„ฐํŽ˜์ด์Šค์—์„œ abstract๋ฉ”์†Œ๋“œ calculate๋งŒ ๊ตฌํ˜„ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

interface Formula {
 double calculate(int a);
 
 default double sqrt(int a) {
 return Math.sqrt(a);
 }
}
Formula formula = new Formula() {
 @Override
 public double calculate(int a) {
 return sqrt(a * 100);
 }
};
 
formula.calculate(100); // 100.0
formula.sqrt(16); // 4.0

Lambda Expressions

Java 8์—๋Š” anonymous objects๋ฅผ ๋งŒ๋“œ๋Š” ๋Œ€์‹ , ํ›จ์”ฌ ๋” ์งง์€ syntax๋ฅผ ๊ฐ€์ง„ Lambda expression์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ์™ผ์ชฝ๊ณผ ๊ฐ™์€ code๋ฅผ Lambda๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์˜ค๋ฅธ์ชฝ๊ณผ ๊ฐ™์ด ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Java ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ parameter type์„ ์•Œ๊ณ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์„ฑ์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Java8 ์ด์ „ ์ฝ”๋“œ

List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
 
Collections.sort(names, new Comparator<String>() {
 @Override
 public int compare(String a, String b) {
 return b.compareTo(a);
 }
});

Lambda ex 1

Collections.sort(names, (String a, String b) -> {
 return b.compareTo(a);
});

์ด code๋ฅผ ๋” ์งง๊ฒŒ ์ค„์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Lambda ex 2

Collections.sort(names, (String a, String b) -> b.compareTo(a));

์—ฌ๊ธฐ์„œ ๋” ์ค„์ธ๋‹ค๋ฉด

Lambda ex 3

Collections.sort(names, (a, b) -> b.compareTo(a));

Functional Interfaces

์–ด๋–ป๊ฒŒ Lambda๊ฐ€ type์„ ์•Œ๊นŒ์š”? ๊ฐ Lambda๋Š” interface๋กœ ์ง€์ •๋œ type์— ๋Œ€์‘์ด ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฑธ Functional Interface๋ผ๊ณ  ๋ถ€๋ฅด๋Š”๋ฐ, ์ •ํ™•ํ•˜๊ฒŒ ํ•˜๋‚˜์˜ abstract ๋ฉ”์†Œ๋“œ ์„ ์–ธ์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ type์˜ Lambda๋Š” ์•ž์„œ ๋งํ•œ abstract ๋ฉ”์†Œ๋“œ์™€ ๋งค์นญ์ด ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ default ๋ฉ”์†Œ๋“œ๋Š” ์ถ”์ƒ์ ์ด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— functional interface์— ์ž์œ ๋กญ๊ฒŒ ์ถ”๊ฐ€ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.

ํ•˜๋‚˜์˜ abstract ๋ฉ”์†Œ๋“œ๋งŒ์„ ํฌํ•จํ•œ ์ž„์˜์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ Lambda๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ธํ„ฐํŽ˜์ด์Šค์— @FunctionalInterface ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์–ด๋…ธํ…Œ์ด์…˜์„ ์•Œ์•„์ฐจ๋ ค์„œ ๋‘๋ฒˆ์งธ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค ๋•Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@FunctionalInterface
interface Converter<F, T> {
 T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted); // 123

Method and Constructor References

functional interfaces์—์„œ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ code๋Š” static ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ๋” ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Java8์—์„œ๋Š” :: ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ๋ฉ”์„œ๋“œ๋‚˜ ์ƒ์„ฑ์ž์˜ ์ฐธ์กฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ์˜ˆ์‹œ๊ฐ€ static method๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

Converter<String, Integer> converter = (from) -> Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted); // 123

object ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

class Something {
 String startsWith(String s) {
 return String.valueOf(s.charAt(0));
 }
}
Something something = new Something();
Converter<String, String> converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted); // "J"

:: ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ์ƒ์„ฑ์ž์— ๋Œ€ํ•œ ์ž‘์—…๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด Person ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  PersonFactory ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์—ˆ์„ ๋•Œ, ์ƒ์„ฑ์ž ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด ์ž๋™์œผ๋กœ ์—ฐ๊ฒฐํ•ด์ค๋‹ˆ๋‹ค.

Person::new๋ฅผ ํ†ตํ•ด Person ์ƒ์„ฑ์ž์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ Java ์ปดํŒŒ์ผ๋Ÿฌ๋Š” PersonFactory.create์™€ ๋งค์นญํ•˜์—ฌ ์˜ฌ๋ฐ”๋ฅธ ์ƒ์„ฑ์ž๋ฅผ ์ž๋™์œผ๋กœ ๋งค์นญํ•ด์ค๋‹ˆ๋‹ค.

class Person {
 String firstName;
 String lastName;
 
 Person() {}
 
 Person(String firstName, String lastName) {
 this.firstName = firstName;
 this.lastName = lastName;
 }
}
interface PersonFactory<P extends Person> {
 P create(String firstName, String lastName);
}
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");

Lambda Scopes

lambda ์‹์—์„œ ์™ธ๋ถ€ ๋ฒ”์œ„(outer scope)๋ฅผ ๊ฐ€์ง„ ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์€ anonymous object์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋กœ์ปฌ ์™ธ๋ถ€ ์Šค์ฝ”ํ”„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ instance ํ•„๋“œ, static ๋ณ€์ˆ˜์—์„œ final ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Accessing local variables

๋‹ค์Œ๊ณผ ๊ฐ™์ด lambda ํ‘œํ˜„์‹์˜ ์™ธ๋ถ€ ๋ฒ”์œ„์—์„œ final ๋กœ์ปฌ ๋ณ€์ˆ˜๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ final์„ ์„ ์–ธํ•˜์ง€ ์•Š์€ ๋ณ€์ˆ˜๋„ ์ปดํŒŒ์ผ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์•”๋ฌต์ ์œผ๋กœ final์œผ๋กœ ์ธ์‹ํ•˜๊ณ  ์ฝ”๋“œ๊ฐ€ ์ปดํŒŒ์ผ๋œ๋‹ค๋Š” ์ ์„ ์ธ์ง€ํ•˜๊ณ  ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

int num = 1; //final int num = 1;
Converter<Integer, String> stringConverter =
 (from) -> String.valueOf(from + num); //implicitly final
 
stringConverter.convert(2); // 3
num = 3 //COMPILE ERROR!!

Accessing fields and static variables

์ธ์Šคํ„ด์Šค ํ•„๋“œ์™€ static ๋ณ€์ˆ˜๋Š” ๋กœ์ปฌ ๋ณ€์ˆ˜์™€ ๋ฐ˜๋Œ€๋กœ lambda ์‹ ๋‚ด์—์„œ์˜ ์ฝ๊ณ  ์“ฐ๊ธฐ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

class Lambda4 {
 static int outerStaticNum; //static variable
 int outerNum; //instance field
 
 void testScopes() {
 Converter<Integer, String> stringConverter1 = (from) -> {
 outerNum = 23;
 return String.valueOf(from);
 };
 
 Converter<Integer, String> stringConverter2 = (from) -> {
 outerStaticNum = 72;
 return String.valueOf(from);
 };
 }
}

Accessing Default Interface Methods

deafult ๋ฉ”์„œ๋“œ๋Š” lambda ์‹์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ์˜ˆ์ œ๋Š” ์ปดํŒŒ์ผ์ด ์•ˆ๋˜๋ฉฐ, Formula๋Š” Deafult Method์—์„œ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

Formula formula = (a) -> sqrt( a * 100); //COMPILE ERROR!!

Built-in Functional Interfaces

JDK 1.8 API๋Š” ๋งŽ์€ ๋‚ด์žฅ functional interface๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Comparator ๋‚˜ Runnable ์™€ ๊ฐ™์€ ์ผ๋ถ€๋Š” Java์˜ ๊ตฌ ๋ฒ„์ „์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋˜ ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค. ์ด ๊ธฐ์กด์˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ™•์žฅ๋˜์–ด @FunctionalInterface ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด Lambda๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ JAVA 8 API๋Š” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด functional interface๋“ค์ด ๋งŽ๊ณ , ์ด๋Ÿฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋“ค ์ค‘ ์ผ๋ถ€๋Š” Google Guava ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ž˜ ์†Œ๊ฐœ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋“ค์ด ์–ด๋–ป๊ฒŒ ์œ ์šฉํ•˜๊ฒŒ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ™•์žฅ๋˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ์ž˜ ์•Œ๊ณ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Predicates (๋งค๊ฐœ๋ณ€์ˆ˜ O, ๋ฐ˜ํ™˜๊ฐ’ O, ๋…ผ๋ฆฌ๊ฐ’ ๋ฐ˜ํ™˜)

Predicate๋Š” ํ•˜๋‚˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ boolean์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ ์ž…๋‹ˆ๋‹ค. ์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์ด ๊ฐ€๋Šฅํ•œ default ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. (and, or, negate)

Predicate<String> predicate = (s) -> s.length() > 0;
 
predicate.test("foo"); // true
predicate.negate().test("foo"); // false
 
Predicate<Boolean> nonNull = Objects::nonNull;
nonNull.test(null); //false

Functions (๋งค๊ฐœ๋ณ€์ˆ˜ O, ๋ฐ˜ํ™˜๊ฐ’ O, ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐ˜ํ™˜)

Function์€ ํ•˜๋‚˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. Function <๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…, ๋ฐ˜ํ™˜๊ฐ’ ํƒ€์ž…>๊ณผ ์‚ฌ์šฉํ•˜๋ฉฐ, apply ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. deafault ๋งค์„œ๋“œ๋“ค์„ chain multiple functions๋กœ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (compose, andThen)

Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
 
backToString.apply("123"); // "123"

Suppliers (๋งค๊ฐœ๋ณ€์ˆ˜ X, ๋ฐ˜ํ™˜๊ฐ’ O)

Supplier๋Š” ์ฃผ์–ด์ง„ generic ํƒ€์ž…์˜ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, get ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. Functions์™€๋Š” ๋‹ฌ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ๊ฒƒ์ด ํŠน์ง•์ž…๋‹ˆ๋‹ค.

Supplier<Person> personSupplier = Person::new;
personSupplier.get(); // new Person

Consumers (๋งค๊ฐœ๋ณ€์ˆ˜ O, ๋ฐ˜ํ™˜๊ฐ’ X)

Consumer๋Š” ํ•˜๋‚˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์„ ํ•ฉ๋‹ˆ๋‹ค. Lambda ์‹์„ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);
greeter.accept(new Person("Luke", "Skywalker")); //Hello, Luke ์ถœ๋ ฅ

Comparators

Comparator๋Š” ๋น„๊ต ๊ทœ์น™์„ ์ •ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ, ์ •๋ ฌ ๊ทœ์น™์„ ์ •ํ•  ๋•Œ ๋งŽ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ตฌ๋ฒ„์ „์˜ Java์—์„œ๋„ ์‚ฌ์šฉ๋˜์—ˆ๊ณ , Java8์—์„œ ์ธํ„ฐํŽ˜์ด์Šค์— ๋‹ค์–‘ํ•œ default method๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);
 
Person p1 = new Person("John", "Doe");
Person p2 = new Person("Alice", "Wonderland");
 
comparator.compare(p1, p2); // > 0
comparator.reversed().compare(p1, p2); // < 0

Optionals

Optional์€ functional interface๊ฐ€ ์•„๋‹ˆ๋ผ NullPointerException์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ niffy ์œ ํ‹ธ๋ฆฌํ‹ฐ์ž…๋‹ˆ๋‹ค. null์ด ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ๊ฐ์‹ธ๋Š” Wrapper ํด๋ž˜์Šค๋กœ, NPE๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

Optional<String> optional = Optional.of("bam"); //of():null์ด ์•„๋‹Œ ๋ช…์‹œ๋œ ๊ฐ’์„ ๊ฐ€์ง€๋Š” Optional ๊ฐ์ฒด ๋ฐ˜ํ™˜
 
optional.isPresent(); // true //Optional ๊ฐ์ฒด์— ์ €์žฅ๋œ ๊ฐ’์ด null์ธ์ง€ ํ™•์ธ
optional.get(); // "bam" //Optional ๊ฐ์ฒด์— ์ €์žฅ๋œ ๊ฐ’ ์ ‘๊ทผ
optional.orElse("fallback"); // "bam" //์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌ-> ๊ฐ’๋ฐ˜ํ™˜, ์—†์œผ๋ฉด-> ์ธ์ˆ˜ ๊ฐ’ ๋ฐ˜ํ™˜
 
optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b"

Streams

java.util.Stream์€ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” elements๋“ค์˜ sequence(์ˆœ์„œ๊ฐ€ ์žˆ๋Š” ์—ฐ๊ฒฐ?)์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. Stream ์—ฐ์‚ฐ์€์€ intermediate์ด๊ฑฐ๋‚˜ terminal ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

terminal ์—ฐ์‚ฐ์€ ํŠน์ • ํƒ€์ž…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ˜๋ฉด, intermediate ์—ฐ์‚ฐ์€ Stream ์ž์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ์—ฐ์†์ ์œผ๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Stream์€ list๋‚˜ set (map์€ ์•ˆ๋จ)๊ณผ ๊ฐ™์€ java.util.Collection๋ฅผ source๋กœ ํ•ด์„œ ๋งŒ๋“ค์–ด์ง€๋ฉฐ, sequential ํ•˜๊ฑฐ๋‚˜ parallelํ•˜๊ฒŒ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์œ ๋ช…ํ•œ stream ์—ฐ์‚ฐ๋“ค์ž…๋‹ˆ๋‹ค. Filter, Sorted, Map์€ intermediate ์—ฐ์‚ฐ์ด๊ณ , Match, Count, Reduce๋Š” terminal ์—ฐ์‚ฐ์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ๋กœ ์‰ฝ๊ฒŒ ์ดํ•ด๊ฐ€ ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์—, ์ž์„ธํ•œ ์„ค๋ช…์€ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

//stringCollection ์€ List๋กœ, {"ddd2", "aaa2", "bbb1", "aaa1", "bbb3", "ccc", "bbb2", "ddd1"}์˜ ์›์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Œ

Filter (ํ•„ํ„ฐ)

stringCollection
 .stream()
 .filter((s) -> s.startsWith("a"))
.forEach(System.out::println);
 
// "aaa2", "aaa1"

Sorted (์ •๋ ฌ)

stringCollection
 .stream()
 .sorted()
 .filter((s) -> s.startsWith("a"))
 .forEach(System.out::println);
 
// "aaa1", "aaa2"

sorted๋Š” ์ •๋ ฌ๋œ view๋งŒ ๋ณด์—ฌ์ค„ ๋ฟ, ์›์†Œ๊ฐ€ ์ •๋ ฌ๋œ ์ƒํƒœ๋กœ ์ €์žฅ๋˜์ง€๋Š” ์•Š์Œ

Map (๋ณ€ํ™˜?)

stringCollection
 .stream()
 .map(String::toUpperCase)
 .sorted((a, b) -> b.compareTo(a))
 .forEach(System.out::println);
 
// "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"

_____Match (์ผ์น˜ ์—ฌ๋ถ€ ํ™•์ธ)

boolean allStartsWithA =
 stringCollection
 .stream()
 .allMatch((s) -> s.startsWith("a"));
 
System.out.println(allStartsWithA); // false
  • anyMatch ์‚ฌ์šฉ: true
  • nonMatch ์‚ฌ์šฉ: true

Count (์š”์†Œ ๊ฐœ์ˆ˜ longํ˜• ๋ฐ˜ํ™˜)

long startsWithB =
 stringCollection
 .stream()
 .filter((s) -> s.startsWith("b"))
 .count();
 
System.out.println(startsWithB); // 3

Reduce (์š”์†Œ๋“ค์„ ์ค„์ด๋Š” ์—ฐ์‚ฐ)

Optional<String> reduced =
 stringCollection
 .stream()
 .sorted()
 .reduce((s1, s2) -> s1 + "#" + s2);
 
reduced.ifPresent(System.out::println);
// "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"

Parallel Streams

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด Stream์€ Sequentialํ•˜๊ฑฐ๋‚˜ Parallelํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Sequential Stream์— ๋Œ€ํ•œ ์—ฐ์‚ฐ์€ ๋‹จ์ผ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๋Š” ๋ฐ˜๋ฉด, Parallel Stream์€ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ์—์„œ ๋™์‹œ์— ์ˆ˜ํ–‰ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์‹œ๋Š” Parallel Stream์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์–ผ๋งˆ๋‚˜ ์‰ฝ๊ฒŒ ๋†’์ผ ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

large list ์ƒ์„ฑ

int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
 UUID uuid = UUID.randomUUID();
 values.add(uuid.toString());
}

Sequential Sort

long t0 = System.nanoTime();
 
long count = values.stream().sorted().count();
System.out.println(count);
 
long t1 = System.nanoTime();
 
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("sequential sort took: %d ms", millis));
 
// sequential sort took: 899 ms

Parallel Sort

long t0 = System.nanoTime();
 
long count = values.parallelStream().sorted().count(); //stream์„ parallelStream์œผ๋กœ ๋ฐ”๊ฟˆ
System.out.println(count);
 
long t1 = System.nanoTime();
 
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("parallel sort took: %d ms", millis));
 
// parallel sort took: 472 ms

Stream ๊ด€๋ จํ•ด์„œ ์•„๋ž˜ ๋งํฌ์— ๋” ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

https://futurecreator.github.io/2018/08/26/java-8-streams/

์ถ”๊ฐ€๋กœ ๋ณด๊ธฐ ์ข‹์€ ๊ธ€

๋žŒ๋‹ค๊ฐ€ ์ด๋Œ์–ด ๊ฐˆ ๋ชจ๋˜ Java

About

java 8 tutorial

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

AltStyle ใซใ‚ˆใฃใฆๅค‰ๆ›ใ•ใ‚ŒใŸใƒšใƒผใ‚ธ (->ใ‚ชใƒชใ‚ธใƒŠใƒซ) /