/*
Stream(스트림)
스트림은 java8부터 추가된 컬렉션, 배열에 저장된 요소(값 or 객체)를 하나씩 꺼내와서 람다식(Functional Interface)
으로 처리할 수 있도록 해주는 반복자이다. Java7까지는 List컬렉션에서 요소를 순차적으로 처리하기 때문에 iterator
를 사용해 왔지만 컬렉션의 Stream()메서드로 Stream객체를 얻은 후에 람다식으로 컬렉션의 요소를 하나씩 처리할 수
있게 되었다.
Iterator와 Stream을 비교해보면 Stream을 사용하는 것이 훨씬 단순하게 사용할 수 있다. Stream은 Iterator와 비슷한
역할을 하는 반복자이지만
1. 람다식으로 처리할 수 있다.
2. 내부반복자를 사용함으로써 병렬처리가 쉽다.
3. 중간처리, 최종처리작업을 수행한다는 점에서 많은 차이가 있다.
Stream의 장점
1. 람다식으로 요소를 처리하는 코드를 제공한다.
Stream이 제공하는 대부분의 메서드는 @FunctionalInterface매개타입을 가지기 때문에 람다식 또한 메서드
참조를 이용해서 요소처리내용을 매개값으로 전달할 수 있다.
2. 내부반복자를 사용함으로써 병렬처리가 쉽다.
외부반복자란 개발자가 코드를 직접 컬렉션의 요소를 반복해서 처리해야 하는 코드를 작성해야 한다는 의미이다.
index를 이용하는 for문 or Iterator를 처리하는 while문을 이용하는 것 모두 외부반복자를 이용하는 것이지만
내부반복자는 Collection 내부에서 요소를 반복시키고 개발자는 요소를 처리해야할 코드만 제공하는 코드패턴을
말한다.
3. 중간처리와 최종처리를 할 수 있다.
스트림은 컬렉션의 요소에 중간처리, 최종처리를 수행할 수 있는데 중간처리는 매핑, 필터링, 정렬 등의 작업을
수행하고 최종처리메서드는 반복, 카운팅, 평균, 합계 등의 처리를 말한다.
*/
public class StreamMain {
public static void main(String[] args) {
List<String> list = Arrays.asList("홍길동", "홍길순", "소향");
// 1. iterator
Iterator<String> names = list.iterator();
while(names.hasNext()) {
String name = names.next();
System.out.println(name+", ");
}System.out.println();
// 2. stream
Stream<String> stream = list.stream();
stream.forEach(name -> System.out.println(name+", "));
}
}
public class LambdaMain {
public static void main(String[] args) {
List<Student> list = Arrays.asList(
new Student("홍길동",95),
new Student("홍길순",91),
new Student("홍길자",98),
new Student("홍길상",92)
);
System.out.println("총 객체수(list.size())="+list.size()); // 외부반복자, 직렬처리
Stream<Student> stream = list.stream();
System.out.println("총 객체수(stream.count())="+stream.count()); // 내부반복자, 병렬처리
System.out.println();
System.out.println("총 객체수(list.size())="+list.size()); //list컬렉션의 속성이기 때문에 정상처리
// 에러발생 : 내부반복자이기 때문에 더이상 꺼내올 자료가 없기 때문에 예외발생
// stream을 다시 사용하려면 stream에 값을 다시 대입한 후에 사용할 수 있다.
//System.out.println("총 객체수(stream.count())="+stream.count()); // 이미 stream을 써버림
stream = list.stream();
// 학생 이름과 점수를 출력
// forEach() 최종처리 메서드
stream.forEach(s -> System.out.println(s.name));
System.out.println();
stream = list.stream();
stream.forEach(s -> System.out.println(s.score));
stream = list.stream();
stream.forEach(s -> System.out.println(s.getScore()));
System.out.println();
stream = list.stream();
stream.forEach(s->{
String name = s.name;
int score = s.score;
System.out.println((name+ "의 점수= "+score));
}); System.out.println();
stream = list.stream();
stream.forEach(s->System.out.println(s.getName()+"의 점수= "+s.getScore()));
}
}
class Student{
public String name;
public int score;
public Student(String name, int score) {
super();
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
}
public class MapAndReduceMain {
public static void main(String[] args) {
List<Student> list = Arrays.asList(
new Student("홍길동",95),
new Student("홍길순",91),
new Student("홍길자",98),
new Student("홍길상",92)
);
// stream의 중간처리와 최종처리
// 1. 학생들의 평균
// 중간처리 mapToInt() -> 최종처리 average() -> 결과값을 리턴 getAsDouble()
double avg = list.stream()
.mapToInt(s->s.getScore())
.average()
.getAsDouble();
System.out.println("학생들의 평균점수= "+avg);
// lambda식의 다른 표현방식
avg = list.stream()
.mapToInt(Student :: getScore)
.average()
.getAsDouble();
System.out.println("학생들의 평균점수= "+avg);
// 2. 학생들의 총점
// 중간처리 mapToInt() -> sum()
System.out.println();
int sum = list.stream()
.mapToInt(Student::getScore)
.sum();
System.out.println("학생들의 총점= "+sum);
sum = list.stream()
.mapToInt(Student::getScore)
.sum();
System.out.println("학생들의 총점= "+sum);
// 3. 학생인원?
// 중간처리 mapToInt() -> count()
long count = list.stream()
.mapToInt(Student::getScore)
.count();
System.out.println("학생들의 수= "+count);
}
}
public class ParallelMain {
public static void main(String[] args) {
List<String> list = Arrays.asList("홍길동","홍길순","홍길자","홍길녀","홍길상");
// 1. 직렬(순차)처리 : stream()
Stream<String> stream = list.stream();
stream.forEach(s->System.out.print(s+",") );
System.out.println();
stream = list.stream();
stream.forEach(s->ParallelMain.print(s) );
System.out.println();
stream = list.stream();
stream.forEach(ParallelMain::print);
// 2. 병렬처리 : parallelStream()
Stream<String> pStream = list.parallelStream();
pStream.forEach(ParallelMain::print);
}
private static void print(String name) {
// System.out.println(name+", ");
System.out.println(name+":"+Thread.currentThread().getName());
}
}
/*
Stream의 종류
java8부터 새로 추가된 java.util.stream 패키지는 stream API들이 포함되어 있다. stream의 종류는
BaseStream과 이 스트림을 구현한 Stream, IntStream, LongStream, DoubleStream이 있다.
BaseStream에는 모든 스트림에서 사용할 수 있는 공통메서드가 정의되어 있을 뿐 코드에서 직접 사용되지는 않는다.
하위 스트림이 직접적으로 사용되는 스트림인데 Stream은 객체의 요소를 처리하는 스트림이고 IntStream, LongStream, DoubleStream은
각각 기본타입인 int, long, double요소를 처리하는 스트림이다.
Stream을 얻는 방법은
1. Collection으로부터 Stream을 얻기
2. Arrays로부터 Stream을 얻기
3. 숫자범위로부터 Stream을 얻기
4. 파일로부터 Stream을 얻기
5. 디렉토리부터 Stream을 얻기
*/
public class FromCollectionMain {
public static void main(String[] args) {
// 1. Collection으로부터 Stream을 얻기
List<Student> list = Arrays.asList(
new Student("홍길동",10),
new Student("홍길동",20),
new Student("홍길동",30)
);
Stream<Student> stream = list.stream();
stream.forEach(s-> System.out.println(s.toString()));
System.out.println();
stream = list.stream();
stream.forEach(System.out :: println);
//System.out.println(s);
//System.out.println(s.toString());
}
}
class Student{
String name;
int score;
@Override
public String toString() {
return this.name+", "+this.score;
}
public Student(String name, int score) {
this.name = name;
this.score = score;
}
}
public class FromArrayMain {
public static void main(String[] args) {
// 2. Arrays로부터 Stream을 얻기
String[] names = {"홍길동","홍길순","홍길자"};
Stream<String> stream = Arrays.stream(names);
stream.forEach(s-> System.out.println(s.toString()));
stream = Arrays.stream(names);
stream.forEach(System.out :: println);
stream = Arrays.stream(names);
stream.forEach(n-> System.out.println(n));
int[] nums = {1,2,3,4,5,6,7,8,9,10};
IntStream is = Arrays.stream(nums);
is.forEach(System.out::println);
System.out.println();
is = Arrays.stream(nums);
is.forEach(i -> System.out.print(i+","));
System.out.println();
double[] d_nums = {1,2,3,4,5,6,7,8,9,10};
DoubleStream ds = Arrays.stream(d_nums);
ds.forEach(d -> System.out.print(d+","));
System.out.println();
long[] l_nums = {1,2,3,4,5,6,7,8,9,10};
LongStream ls = Arrays.stream(l_nums);
ls.forEach(l -> System.out.print(l+","));
System.out.println();
}
}
public class FromRangeMain {
// stream에서 사용되는 변수는 static으로 선언해야 한다.
// 또한, 클래스멤버로 선언되야 한다.
static int sum = 0;
public static void main(String[] args) {
//3. 숫자범위로부터 Stream을 얻기
IntStream stream = IntStream.range(1, 5);
stream.forEach(n->sum+=n);
System.out.println("1~4까지 합 = "+sum);
sum = 0;
stream = IntStream.rangeClosed(1, 5);
stream.forEach(n->sum+=n);
System.out.println("1~5까지 합 = "+sum);
}
}
public class FromFileMain {
public static void main(String[] args) throws IOException {
// 4. 파일로부터 Stream을 얻기
Stream<String> stream = null;
//1) 파일위치
Path path = Paths.get("D:\\Yeonsu/05.java/java16.stream/src/com/lec/ex02_kind/datafile.text");
System.out.println(path);
System.out.println();
//2) 파일읽기(1) - java.nio.file.Files.lines()메서드 이용
stream = Files.lines(path);
stream.forEach(System.out::println);
System.out.println();
//3) 파일읽기(2) - java.io.BufferdReader.line()메서드 이용
File file = path.toFile();
FileReader fileReader = new FileReader(file);
BufferedReader br = new BufferedReader(fileReader);
stream = br.lines();
stream.forEach(System.out::println);
stream.close();
br.close();
fileReader.close();
}
}
public class FromDirectoryMain {
public static void main(String[] args) throws IOException {
// 5. 디렉토리부터 Stream을 얻기
Path path = Paths.get("D:\\\\Yeonsu/05.java");
Stream<Path> stream = Files.list(path);
stream.forEach(System.out::println);
System.out.println();
stream = Files.list(path);
// stream.forEach(p->System.out.println(p.getFileName()));
stream.forEach(p->System.out.println(p.getName(0)+", "+p.getName(1)+", "+p.getName(2)));
System.out.println();
}
}
'일 > JAVA' 카테고리의 다른 글
java16.stream.aggregate (0) | 2023.05.30 |
---|---|
java16.stream.pipeline (0) | 2023.05.30 |
java15.collection (0) | 2023.05.26 |
java14.lambda 람다람다 (0) | 2023.05.26 |
java13.generic (1) | 2023.05.26 |