Stream
-> Generices
-> Lambda
-> 함수형 인터페이스
배열 및 컬렉션에 저장된 요소를 반복 처리하기 위해서는 for문을 이용하거나 lterator를 이용한다
Java8부터 배열 및 컬렉션을 다루기 위해서 Stream이 사용가능하다
반복문과 Iterator :: 외부 반복자
Stream 은 원소의 처리를 위해서 컬렉션 내부로 주입시켜서 처리 하는 :: 내부 반복자
Function Package :: 함수형 인터페이스
java8 부터 배열 및 컬렉션을 다루기 위해 Stream 사용
대량의 데이터를 배열이나 컬렉션을 스트림으로 변환해서
원소를 꺼내어서 일일히 다루지 않고
처리해야할 내용을 함수형 인터페이스를 통해서 정의만
해주면 내부 반복을 통해서 결과를 생성.
기술적으로 Fork 와 Join을 활용
package p10_Stream;
public class Ex01Stream {
public static void main(String[] args) {
//Stream : 데이터를 처리하는 코드에만 집중
//반복되는 요소는 컬렉션이 처리
//1) 데이터 변경 안함 2) 일회용 3) 내부반복작업
Stream<Student> stream = Stream.of(
new Student("김자바",1, 200),
new Student("이자바",1, 200),
new Student("박자바",1, 200),
new Student("정자바",1, 200),
new Student("최자바",1, 200),
new Student("성자바",1, 200),
new Student("안자바",1, 200),
new Student("전자바",1, 200),
new Student("홍자바",1, 200)
);
}
}
Comparable<Student> 작성해주고
compareTo를 오버라이드 해준다
class Student implements Comparable<Student>{
String name;
int ban;
int totalScore;
@Override
public int compareTo(Student s) {
return -1*(totalScore-s.totalScore);
}
public Student(String name, int ban, int totalScore) {
this.name = name;
this.ban = ban;
this.totalScore = totalScore;
}
public String toString() {
return String.format("[%s, %d, %d]", name, ban, totalScore);
}
public String getName() {
return name;
}
public int getBan() {
return ban;
}
public int getTotalScore() {
return totalScore;
}
}
stream을 정렬하는 메서드를 적용하고 비교하는 객체를 Comparator.comparing
package p10_Stream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Optional;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Ex04Stream {
public static void main(String[] args) {
// Stream: 데이터를 처리하는 코드에만 집중
// 반복되는 요소는 컬렉션이 처리할 수 있게 함.
// 1) 데이터 변경 안함,2)일회용, 3) 내부반복작업
// Stream을 통하여 데이터를 모은다.
Stream<Student> stream = Stream.of(
new Student("김자바", 3, 300),
new Student("이자바", 3, 200),
new Student("박자바", 2, 200),
new Student("정자바", 2, 200),
new Student("최자바", 1, 200),
new Student("성자바", 1, 200),
new Student("안자바", 3, 200),
new Student("전자바", 1, 200),
new Student("홍자바", 2, 100)
);
/* // stream을 정렬하는 메서드를 적용하고 비교하는 객체를 Comparator.comparing
stream.sorted(Comparator.comparing(new Function<Student, Integer>() {
@Override
public Integer apply(Student student) {
return student.getBan(); //반별로 묶어 준다.
}
// 반별로 묶은 것을 반을 naturalOrder(오름차순)로 정렬한다.
}).thenComparing(Comparator.naturalOrder())).forEach(new Consumer<Student>() {
@Override
public void accept(Student student) {
System.out.println(student); //정렬후 각각에 대하여 출력한다.
}
});
*/
// Optional 객체 사용하여 totalScore 점수가 가장 큰 사람 구하기
// 함수형 인터페이스 Fuction에 매개변수를 2개받기 위해 만든 함수.
/*Optional<Student> student = stream.reduce(new BinaryOperator<Student>() {
@Override
public Student apply(Student s1, Student s2) {
return s1.totalScore > s2.totalScore ? s1 : s2;
}
});
if(student.isPresent()) System.out.println(student);*/
// stream을 배열로 변환
/*System.out.println(Arrays.toString(stream.toArray(Student[]::new)));
System.out.println(Arrays.toString(stream.toArray(new IntFunction<Student[]>() {
@Override
public Student[] apply(int value) {
return new Student[value];
}
})));*/
// 학생 전체 인원수 구하기
/*System.out.println(stream.count());
System.out.println(stream.collect(Collectors.counting()));*/
// 학생모두의 합계 구하기
/*System.out.println(stream.collect(Collectors.summingInt(
new ToIntFunction<Student>() {
@Override
public int applyAsInt(Student s) {
return s.getTotalScore();
}
})));*/
System.out.println(stream.collect(Collectors.maxBy(
Comparator.comparingInt(new ToIntFunction<Student>() {
@Override
public int applyAsInt(Student s) {
return s.getTotalScore();
}
})
)));
}
}
class Student implements Comparable<Student> {
String name; int ban;int totalScore;
public Student(String name, int ban, int totalScore) {
this.name = name;this.ban = ban;this.totalScore = totalScore;
}
@Override
public int compareTo(Student s) {return -1*(totalScore-s.totalScore); }
public String toString(){
return String.format("[%s, %d, %d]", name,ban,totalScore);}
public String getName() {return name;}
public int getBan() {return ban;}
public int getTotalScore() {return totalScore;}
}
package p10_Stream;
import com.sun.nio.sctp.AbstractNotificationHandler;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
public class Ex01ArrayCollection {
public static void main(String[] args) {
String[] stArr1 = {"abc", "def", "ghi"};
// 배열을 Stream으로 변경
Stream<String> tmpStream = Arrays.stream(stArr1);
tmpStream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
String[] stArr2 = {"ABC", "DEF", "GHI"};
//2개의 배열을 하나의 Stream으로 변경
Stream<String[]> arraysStream = Stream.of(stArr1, stArr2);
// 배열 스트림을 String Stream으로 변경
Stream<String> strStream = arraysStream.flatMap(
// String[], String을 상속받은 ?::객체
new Function<String[], Stream<? extends String>>() {
@Override
public Stream<? extends String> apply(String[] array) {
return Arrays.stream(array);
}
}).map(new Function<String, String>() {
@Override
public String apply(String s) {
return s.toLowerCase();
}
});
strStream.distinct().sorted().forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
}
}
List<String> list = new ArrayList<String>();
list.add("손흥민");
list.add("황희찬");
list.add("황인범");
list.add("김민재");
Stream<String> nameStream = list.stream();
nameStream.forEach(s ->{
System.out.println(s);
System.out.println(s.toLowerCase());
});
parallelStream은 스트림의 요소를 병렬로 처리하여
대용량 데이터 처리 시 성능을 향상시킬 수 있는 강력한 도구입니다.
그러나 사용 시 성능 오버헤드, 스레드 안전성, 순서 보장 등의 문제를 고려해야 합니다.
병렬 스트림을 적절하게 사용하면, 멀티코어 프로세서의 성능을 최대한 활용하여
효율적인 데이터 처리가 가능합니다.
//ForkJoinPool관리 방식을 사용해서 복잡하던 스레드 관리방식을 Fork와 Joind을 통해서
//분할 정보(Divide and Conquer) 기법으로 처리해준다.
Stream<String> nameStream1 = list.parallelStream();
nameStream1.forEach(s ->{
System.out.println(s);
});
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;
public class Ex02StreamRange {
public static void main(String[] args) {
IntStream intStream = new Random().ints(1,5);
intStream.limit(5).forEach(new IntConsumer() {
@Override
public void accept(int value) {
System.out.println(value);
}
});
//intStream.limit(5).forEach(value -> System.out.println(value));
//intStream.limit(5).forEach(System.out::println);
}
}
// range의 끝수는 제외
LongStream longStream = LongStream.range(1, 46);
longStream.forEach(new LongConsumer() {
@Override
public void accept(long value) {
System.out.println(value);
}
});
//rangeClosed()는 끝번호 포함
IntStream intStream1 = IntStream.rangeClosed(1, 45);
intStream1.forEach(new IntConsumer() {
@Override
public void accept(int value) {
System.out.println(value);
}
});
Stream<Integer> itrStream = Stream.iterate(0, n -> n + 2);
itrStream.limit(5).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
IntStream lottoStream = new Random().ints(1,46);
lottoStream.distinct().limit(6).forEach(new IntConsumer() {
@Override
public void accept(int value) {
System.out.printf("%3d",value);
}
});
fileListStream.map은 Java Stream API를 사용하여
스트림(Stream<T>)의 각 요소를 변환하는 데 사용됩니다.
map 메서드는 스트림의 각 요소에 함수를 적용하여 새로운 요소를 생성하고,
이 새로운 요소들로 구성된 새로운 스트림을 반환합니다.
package p10_Stream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Ex03StreamMidOperator {
public static void main(String[] args) {
String dir = "C:/"; //경로 생성
try {
Stream<Path> fileListStream = Files.list(Paths.get(dir)); //
//map
fileListStream.map(new Function<Path, Object>() {
@Override
public Object apply(Path path) {
return path.toFile();
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
fileListStream.map은 스트림의 각 요소를 특정 함수에 적용하여 새로운 요소로 변환하는 데 사용됩니다.
map 메서드는 변환 작업을 간결하고 직관적으로 처리할 수 있게 해주며,
다양한 변환 작업에 유용하게 사용될 수 있습니다
요약
- 동작: filter 메서드는 스트림의 요소를 주어진 조건(predicate)으로 테스트하여, 조건을 만족하는 요소들만을 포함하는 새로운 스트림을 반환합니다.
- 용도: filter는 데이터 스트림에서 특정 조건에 맞는 요소들만을 선택하는 데 사용됩니다.
- 결과: filter를 통해 생성된 새로운 스트림은 원래 스트림의 일부 요소만을 포함하며, 이 새로운 스트림에 대해 추가적인 스트림 연산을 수행할 수 있습니다.
filter 메서드를 사용하면 스트림의 요소를 효율적으로 선택하고 처리할 수 있으며,
코드의 가독성과 유지보수성을 높이는 데 도움이 됩니다.
.filter(new Predicate<Object>() {
@Override
public boolean test(Object o) {
File file =(File) o;
return file.isFile();
}
})
package p10_Stream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Ex03StreamMidOperator {
public static void main(String[] args) {
String dir = "C:\\workspace\\spaceJava\\20240611_java"; //경로 생성
try {
Stream<Path> fileListStream = Files.list(Paths.get(dir));
fileListStream
//n개가 들어오면 n개의 각각에 대하여 처리할 것을 정의
.map(new Function<Path, File>() {
@Override
public File apply(Path path) {
return path.toFile();
}
})
// .peek(new Consumer<File>() {
// @Override
// public void accept(File f) {
// System.out.println(f.toString() + ",");
// }
// })
//n개가가 들어와서 필터링을 거쳐 m개를 리턴함.
.filter(new Predicate<File>() {
@Override
public boolean test(File o) {
File file = (File) o;
return file.isFile();
}
})
.map(new Function<File, String>() {
@Override
public String apply(File file) {
return file.toString();
}
})
.map(new Function<String, String>() {
@Override
public String apply(String s) {
return s.toUpperCase();
}
})
.distinct() //중복을 제거해줌
//각각의 원소에 대해서 적용 입력은 있지만, 출력은 없다
.forEach(new Consumer<String>() {
//retrun 타입이없고, 소비만 하고 끝남
@Override
public void accept(String s) {
System.out.println(s);
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
'PROGRAMING📚 > Java📑' 카테고리의 다른 글
Java::활용 -Network (0) | 2024.07.05 |
---|---|
Java::Thread (0) | 2024.07.05 |
Java::활용 - List (0) | 2024.07.05 |
Java:: 입출력 Stream I/O (0) | 2024.06.27 |
Java :: 활용 -String (0) | 2024.06.25 |
댓글