람다
(인자 리스트) -> {바디}
인자 리스트
바디
Iterable 예시를 보자. 실제 사용하는 람다식도 이 이터레이터 자료구조에서 forEach()을 도출해서 사용하는 경우가 많다.
Iterable<UserEntity> userList = userService.getUserByAll();
List<ResponseUser> result = new ArrayList<>();
userList.forEach( v -> {
result.add(new ModelMapper().map(v, ResponseUser.class)); // forEach(), map() 자주 쓰는 방식
});
자 그럼 람다식을 사용하면서 기본적인 방식을 정리해보자.
기존
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
람다식
이라면 이렇게 인라인
으로 메서드 이름만으로 어떤연산을 하는 것인지 바로 알 수 있게 해준다.
선언식 프로그래밍 방식, 함수형 프로그래밍 방식임
IntStream.range(0, 10).forEach((int value) -> System.out.println(value));
기존
int sum;
int[] arr = {1,2,3,4,5};
sum = Arrays.stream(arr).sum();
System.out.println("합 : " + sum);
람다식
static int sum;
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.stream().forEach((i) -> { sum += i;});
System.out.println("합 : " + sum);
https://napasun-programming.tistory.com/32
// iterator 구성 방식
Iterator iter = list.iterator();
// stream 구성 방식
Stream stream = list.stream();
// => 완전 똑같다!
iterator hasNext() 표현식
while (iter.hasNext() == true) {
Object next = iter.next();
System.out.println("next: "+ next);
}
중급 57)
// foreach 람다 형식을 이용하여 List 출력하기
List<Integer> mmlists = Arrays.asList(1,2,3,4,5);
mmlists.stream() // stream() 안써도 됨
.forEach(m -> System.out.println(m));
중급 58)
// for와 if를 이용하여 홀수에 대한 제곱의 합 구하기
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
int sum = 0;
for(Integer odd : list) {
if(odd%2 == 1) {
sum += odd*odd;
}
}
System.out.println("sum: "+ sum);
}
중급 59)
// stream을 이용하여 홀수의 합 구하기
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
int sum = 0;
sum = list.stream()
.filter(d -> d % 2 == 1)
.reduce(0, Integer::sum);
System.out.println(sum);
중급 60)
// stream과 map을 이용하여 홀수에 대한 제곱의 합 구하기
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
int sum = 0;
System.out.println(
list.stream()
.filter(d -> d%2 == 1) // filter 가 if 형식으로! list로 반환 vs map가 비교!
.map(d -> d*d) // boolean값으로 반환
.collect(Collectors.toList())
);
sum = list.stream()
.filter(d -> d%2 == 1)
.map(d -> d*d)
.reduce(0, Integer::sum); // 앞인자 0을 안넣으면? OptionalInt[sum]으로 됨!
System.out.println("sum: "+ sum);
중금 ##)
List<String> strList = Arrays.asList("kobi", "dsg", "lbk");
long count = strList
.stream()
.filter(x -> x.contains("s"))
.count();
중금 ##)
IntStream intStream = IntStream.rangeClosed(1, 45);
intStream
.filter(i -> i % 2 ==0)
.limit(10)
.forEach(System.out::println);
mapToInt
: intStream으로 변환 * Stream에서 sum()메서드를 사용할려면 IntStream
, LongStream
, DoubleStream
와 같은 기본형특화스트림으로 해줘야 한다.그래서 보통 mapToInt, mapToLong, mapToDouble로 스트림을 변환해주고 사용한다. => sum(), average(), max(), min()
https://bcp0109.tistory.com/299
List<Integer> inst = Arrays.asList(1,2,3);
// reduce
int sum = inst.stream()
.reduce(0, Integer::sum);
// sum
int sum = inst.stream()
.mapToInt(i -> i)
.sum();
// average
int average = intlist.stream()
.filter(i -> i % 2 == 0)
.mapToInt(i -> i)
.average(); // sum()같은 것
// peek : 슬쩍 연산 그래서 특정 작업을 수행할 뿐 결과에 영향을 안 미친다!
Stream.of(1,2,3,4)
.peek(System.out::println) // 슬쩍 본다.
.reduce(Integer::sum);
// of
int sum = Stream.of(1, 2, 3)
.mapToInt(i -> i)
.sum();
// mapToInt
List<String> strl = Arrays.asList("dsg1", "kmb2", "tkj3");
strl.stream()
.map(s-> s.substring(3))
.mapToInt(Integer::parseInt)
.forEach(System.out::println);
List<String> strings = Arrays.asList("10 ", "11", "13 ", "15");
strings.stream()
.map(s->s.trim())
.mapToInt(Integer::parseInt)
.forEach(System.out::println);
// flatMap
// 스트림의 각 요소를 "다른 스트림"으로 변환(평면화)
List<String> strings = Arrays.asList("This", "is", "list", "a", "of", "strings");
List<String> collect1 = strings.stream()
.flatMap(s -> Arrays.stream(s.split("")))
.collect(Collectors.toList());
System.out.println("collect1 = " + collect1);
// collect1 = [T, h, i, s, i, s, l, i, s, t, a, o, f, s, t, r, i, n, g, s]
// flatMapToInt
// 기존 방식 ;; 람다 쓰면 더 편한것!
List<String> intList = Arrays.asList(" 10", " 2", " 3", " 4");
intList.stream()
.flatMapToInt(data -> {
System.out.println("######"+ data);
String[] strArr = data.split(",");
int[] intArr = new int[strArr.length];
for(int i = 0; i<strArr.length; i++) {
intArr[i] = Integer.parseInt(strArr[i].trim());
}
return Arrays.stream(intArr);
})
.forEach(number -> System.out.println(number));
// Arrays.stream()
// 연습문제 : 이 텍스트에 "-", " " 를 없애고 int로 parsing하여 합을 구하시오.
String str = "11-9-2-8-48-39- 28-2-82- 94-9-48-2";
str = str.replace(" ", "");
String[] strArr = str.split("-");
int sum = Arrays.stream(strArr)
.sorted()
.mapToInt(Integer::parseInt)
.sum();
System.out.println("sum: "+ sum);
// boxed() : primitive type의 Stream을 reference type의 Stream으로 변환
List<String> intList = Arrays.asList(" 10", " 2", " 3", " 4");
List<Integer> collect3 = intList.stream()
.map(it -> it.replaceAll(" ", ""))
.mapToInt(Integer::parseInt)
.boxed()
.collect(Collectors.toList());
// 매칭(Match)
// allMatch: Stream의 모든 요소가 주어진 Predicate에 일치하는지 확인
var match1 = intlist.stream()
.allMatch(i -> i % 2 == 0);
// anyMatch: Stream의 어떤 요소가 주어진 Predicate에 일치하는지 확인
var match2 = intlist.stream()
.anyMatch(i -> i % 2 == 0);
// noneMatch: Stream의 어떤 요소도 주어진 Predicate에 일치하지 않는지 확인
var match3 = intlist.stream()
.noneMatch(i -> i % 2 == 0);
System.out.println("match1: "+ match1);
System.out.println("match2: "+ match2);
System.out.println("match3: "+ match3);
// 결과
match1: false
match2: true
match3: false
List<Subject> subjects = Arrays.asList(
new Subject("dsg", 40),
new Subject("math", 60)
);
List<Student> students = Arrays.asList(
new Student("dsg", 20223303),
new Student("dsg1", 3455323),
new Student("ss1", 3455323),
new Student("dsg2", 78990999)
);
// filter, map
List<Student> collect = students.stream()
.filter(student -> student.getName().contains("dsg"))
.map(it -> {
it.getSubjectList().add(new Subject("math", 100));
return it;
}
).collect(Collectors.toList());
System.out.println("collect = " + collect);
// rangeClosed
// mapToObj: mapToObj 메서드는 map 메서드와 비슷하지만, 기존의 primitive 타입을 객체 타입으로 변환할 때 사용
// mapToObj -> int 숫자들을 -> Dto의 필드에 각각 set 변환
List<SampleDTO> memberList = IntStream
.rangeClosed(1, 20)
.asLongStream()
.mapToObj(i -> {
return SampleDTO.builder()
.sno(i)
.first("First.." + i)
.last("Last.." + i)
.regTime(LocalDateTime.now())
.build();
}).collect(Collectors.toList());
//1) 이중 for문 => 이중 stream
// 객체 -> Student + Subject
List<Student> students = Arrays.asList(
new Student("dsg", 23),
new Student("ert", 28),
new Student("hhh", 21),
new Student("dsg1", 29)
);
List<Subject> subjects = Arrays.asList(
new Subject(1L, "ert", 30),
new Subject(2L, "ert", 32),
new Subject(3L, "dsg", 30),
new Subject(4L, "dsg", 40),
new Subject(5L, "dsg", 70)
);
// forEachx2개 -> 이중 stream : 먼저 하위객체부터
subjects.stream().forEach(subject -> {
students.stream().filter(student -> student.getName().equals(subject.getName()))
.forEach(student -> student.add(subject));
});
System.out.println("Students = " + students); // => json rest api
//2) 이중 for문 => 이중 stream
List<Company> companies = new ArrayList<>();
companies.add(new Company("Company 1"));
companies.add(new Company("Company 2"));
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("John", 30));
employees.add(new Employee("Jane", 25));
employees.add(new Employee("Jim", 35));
employees.stream().filter(employee -> employee.getAge() >= 10).forEach(employee -> {
companies.forEach(company -> company.getEmployees().add(employee));
});
// flatMap() : Array나 Object로 감싸져 있는 모든 원소를 단일 원소 스트림으로 반환해준다
// 이중stream을 위해 먼저 하위부터!
List<Company> updatedCompanies = employees.stream()
.flatMap(employee -> companies.stream().filter(company -> company.getName().equals(employee.getName())).map(company -> {
company.getEmployees().add(employee);
return company;
})).distinct().collect(Collectors.toList());
groupingBy()
: sql의 groupby랑 비슷List<Cat> cats = Arrays.asList(
new Cat("f", "happy"),
new Cat("f", "sujan"),
new Cat("m", "pasan")
);
Map<String, List<Cat>> catsex =
cats.stream()
.collect(
Collectors.groupingBy(Cat::getSex) // Cat sex 기준으로 묶음
);
System.out.println(catsex);
Map<String, List<String>> group =
cats.stream()
.collect(
Collectors.groupingBy(
Cat::getSex,
Collectors.mapping(Cat::getName, Collectors.toList()) // Cat sex, name 기준으로 묶음
)
);
System.out.println(group);
결과값
-> mapping까지 해주는 것이 결과값으로 깔끔!