반응형
jdk 8
Function 인터페이스
- 파라미터와 리턴이 존재하는 메소드 표현
/*Function<String, Integer> toInt = new Function<String, Integer>() {
@Override
public Integer apply(String value) {
return Integer.parseInt(value);
}
};*/
Function<String, Integer> toInt = (value) -> Integer.parseInt(value);
System.out.println(toInt.apply("100"));
Predicate 인터페이스
- 파라미터와 리턴이 존재하는 메소드 표현
- Function과의 차이는 boolean만 반환함
Predicate<Integer> isPositive = (value) -> value > 0;
System.out.println(isPositive.test(5));
Supplier 인터페이스
- 리턴만 존재하는 메소드를 표현
Supplier<String> supplier = () -> "Hello World";
System.out.println(supplier.get());
Consumer 인터페이스
- 리턴이 필요없는 메소드를 표현
Consumer<String> print = (value) -> System.out.println(value);
print.accept("Hello World");
사용자 지정 인터페이스
@FunctionalInterface
public interface CustomFunction<P1, P2, P3, R> {
R apply(P1 param1, P2 param2, P3 param3);
}
CustomFunction<Integer, Integer, Integer, Integer> function = (param1, param2, param3) -> param1 + param2 + param3;
System.out.println(function.apply(1, 2, 3));
range()
// 0 ~ 9
IntStream.range(0, 10).forEach(i -> System.out.print(i + " "));
// 0 ~ 10
IntStream.rangeClosed(0, 10).forEach(i -> System.out.print(i + " "));
of()
// 1 ~ 5
Stream.of(1, 2, 3, 4, 5).forEach(i -> System.out.print(i + " "));
iterate()
// 무한으로 증가
//IntStream.iterate(0, i -> i + 1).forEach(i -> System.out.print(i + " "));
Stream.iterate(BigInteger.ZERO, i -> i.add(BigInteger.ONE)).forEach(i -> System.out.print(i + " "));
filter(), map()
// 아래 예제에서는 filter1에서 numbers를 모두 루프, filter2에서 numbers를 모두 루프하는 방식이 아님 (효율적으로 처리)
// 전체 numbers를 루프 돌리는 도중 filter1, filter2, map, filter3을 체크하는 구조
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Optional<Integer> result = numbers.stream()
.filter(number -> number > 3)
.filter(number -> number < 9)
.map(number -> number * 2)
.filter(number -> number > 10)
.findFirst();
System.out.println(result);
collect()
List<String> resultList = Stream.of(1, 2, 3, 4, 5)
.filter(i -> i > 2)
.map(i -> i * 2)
.map(i -> "#" + i)
.collect(Collectors.toList());
Set<String> resultSet = Stream.of(1, 3, 3, 5, 5)
.filter(i -> i > 2)
.map(i -> i * 2)
.map(i -> "#" + i)
.collect(Collectors.toSet());
System.out.println(resultList);
System.out.println(resultSet);
joining()
String result1 = Stream.of("1", "2", "3").collect(Collectors.joining());
System.out.println(result1);
String result2 = Stream.of("1", "2", "3").collect(Collectors.joining(", "));
System.out.println(result2);
String result3 = Stream.of("1", "2", "3").collect(Collectors.joining(", ", "[", "]"));
System.out.println(result3);
distinct()
List<Integer> result = Stream.of(1, 2, 2, 3).distinct().collect(Collectors.toList());
System.out.println(result);
count()
long count = Stream.of(1, 2, 3).count();
System.out.println(count);
sum()
// IntStream의 경우 sum() 사용 가능
int sum = IntStream.of(1, 2, 3, 4, 5).sum();
System.out.println(sum);
reduce()
int sum = Stream.of(1, 2, 3, 4, 5).reduce(0, (total, current) -> total + current);
assertEquals(15, sum);
groupBy()
@RequiredArgsConstructor
@Getter
public class User {
private final String type;
private final String name;
private final int age;
}
List<User> users = List.of(
new User("google", "john", 25),
new User("google", "tom", 30),
new User("kakao", "jane", 28)
);
Map<String, List<User>> typeUsersMap = users.stream()
.collect(Collectors.groupingBy(
User::getType
));
assertEquals(2, typeUsersMap.get("google").size());
assertEquals(1, typeUsersMap.get("kakao").size());
Map<String, Long> typeCountMap = users.stream()
.collect(Collectors.groupingBy(
User::getType,
Collectors.counting()
));
assertEquals(2, typeCountMap.get("google"));
assertEquals(1, typeCountMap.get("kakao"));
Map<String, Double> typeAgeMap = users.stream()
.collect(Collectors.groupingBy(
User::getType,
Collectors.averagingDouble(User::getAge)
));
assertEquals(27.5, typeAgeMap.get("google"));
assertEquals(28.0, typeAgeMap.get("kakao"));
parallel()
- 멀티 코어 프로세싱 처리로 속도가 빠름
- 동기화 문제가 발생할 수 있음
long start = System.currentTimeMillis();
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8)
.stream()
.parallel()
.map(i -> {
try { Thread.sleep(1); } catch (InterruptedException e) { }
return i;
})
.forEach(i -> System.out.print(i + " "));
System.out.println();
System.out.println(System.currentTimeMillis() - start);
parallelStream()
- stream() + parallel()
long start = System.currentTimeMillis();
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8)
.parallelStream()
.map(i -> {
try { Thread.sleep(1); } catch (InterruptedException e) { }
return i;
})
.forEach(i -> System.out.print(i + " "));
System.out.println();
System.out.println(System.currentTimeMillis() - start);
참고
jdk 9
불변 Collection 생성 메서드 제공
List<String> immutableList = List.of("1", "2", "3");
Map<String, Integer> immutableMap = Map.of("1", 1, "2", 2, "3", 3);
try-with-resources 개선
void tryWithResourcesByJava7() throws IOException {
BufferedReader reader1 = new BufferedReader(new FileReader("test.txt"));
try (BufferedReader reader2 = reader1) {
// do something
}
}
// final or effectively final이 적용되어 reader 참조를 사용할 수 있음
void tryWithResourcesByJava9() throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("test.txt"));
try (reader) {
// do something
}
}
인터페이스 내에서 private 메서드 사용 가능
interface Calculator {
int plus(int a, int b);
default int minus(int a, int b) {
print();
return a - b;
}
private void print() {
System.out.println("Hello Minus");
}
}
class BasicCalculator implements Calculator {
@Override
public int plus(int a, int b) {
return a + b;
}
}
Calculator calculator = new BasicCalculator();
System.out.println(calculator.plus(1, 2));
System.out.println(calculator.minus(1, 2));
Reactive Stream 도입
@RequiredArgsConstructor
@Data
public class Student {
private final int id;
private final String name;
}
public class StudentSubscriber implements Flow.Subscriber<Student> {
public static int count = 0;
private Flow.Subscription subscription;
@Override
public void onSubscribe(Flow.Subscription subscription) {
this.subscription = subscription;
this.subscription.request(1);
}
@Override
public void onNext(Student student) {
System.out.println("process : " + student);
count++;
this.subscription.request(1);
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("complete when publisher closed");
}
}
List<Student> students = List.of(
new Student(1, "john"),
new Student(2, "tom"),
new Student(3, "jane")
);
SubmissionPublisher<Student> publisher = new SubmissionPublisher<>();
publisher.subscribe(new StudentSubscriber());
students.forEach(publisher::submit);
while (StudentSubscriber.count != students.size()) {
System.out.println("wait");
Thread.sleep(1000);
}
publisher.close();
System.out.println("finish");
wait
process : Student(id=1, name=john)
process : Student(id=2, name=tom)
process : Student(id=3, name=jane)
finish
complete when publisher closed
Stream Method 추가
- iterate()
IntStream .iterate(0, i -> i < 5, i -> i + 1) .forEach(i -> System.out.print(i + " ")); // 1 2 3 4
- takeWhile()
Stream .of(1, 2, 3, 4, 5, 6) .takeWhile(i -> i <= 3) .forEach(i -> System.out.print(i + " ")); // 1 2 3
- dropWhile()
Stream .of(1, 2, 3, 4, 5, 6) .dropWhile(i -> i <= 3) .forEach(i -> System.out.print(i + " ")); // 4 5 6
참고
jdk 10
Local-variable type inference
var numbers = List.of(1, 2, 3);
for (var number : numbers) {
System.out.println(number);
}
타입 추론이 안되는 경우
var x = null; // null assign 불가
var x; // 초기화 없이 사용 불가
public var x = 10; // local 변수가 아닌 경우
var x = {1, 2, 3}; // array initializer 불가
public void add(var a, var b) {} // 메소드 인자로 사용 불가
참고
jdk 11
(JEP 321) HTTP Client (Standard)
- jdk9에서 인큐베이터 패키지로 추가, jdk11에서 정식 패키지로 추가
- Non-Blocking request and response 지원 (with CompletableFuture)
- Backpressure 지원(
java.util.concurrent.Flow
패키지를 통해 RX Flow를 구현체에 적용) - HTTP/2 지원
- Factory method 형태로 지원
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8080/api/tests"))
.timeout(Duration.ofMinutes(1))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"name\" : \"john\"}"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.headers());
System.out.println(response.body());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8080/api/tests"))
.timeout(Duration.ofMinutes(1))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"name\" : \"john\"}"))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(response -> {
System.out.println(response.statusCode());
System.out.println(response.headers());
return response;
})
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
참고
jdk 12
(JEP325) Switch Expressions (Preview)
- jdk13에서 제공될 예정
- 예시
switch (alphabet) { case "a", "b" -> System.out.println("a, b"); case "c" -> System.out.println("c"); }
int number = switch (alphabet) { case "a", "b" -> 1; case "c" -> 2; default -> throw new IllegalStateException("others"); };
String 클래스
System.out.println("Hello\nWorld".indent(4));
System.out.println("Hello world".transform(s -> s.replace("Hello", "Bye")).toString());
참고
jdk 13
Text Blocks
String json = """
{
"name": "john",
"age": 25
}
""";
System.out.println(json);
Switch Expressions
- 반환문이 break에서 yield로 변경됨
String result = switch (number) {
case 1:
case 2:
yield "number1 or 2";
default:
yield "default";
};
참고
jdk 14
JEP 305: Pattern Matching for instanceof (Preview)
- instanceof 체크 후 캐스팅 과정 필요없어짐
// before
if (obj instanceof String) {
String text = (String) obj;
}
// after
if (obj instanceof String s) {
if (s.length() > 2) {
// ...
}
}
JEP 359: Records (Preview)
public record Student(
String name,
int age
) {}
Student student = new Student("john", 24);
System.out.println(student.name());
System.out.println(student.age());
참고
반응형
'Development > Java' 카테고리의 다른 글
[Java] Markdown 파싱 (0) | 2020.12.28 |
---|---|
[Java] VisualVM 사용하기 (0) | 2019.09.30 |
[Java] XML 파싱 (0) | 2019.03.20 |
[Java] Json Handling(with Jackson) (0) | 2019.03.20 |
[Java] HTML 파싱 (0) | 2019.03.20 |