본문 바로가기
JAVA

Stream

by 요리하다그만둠 2022. 6. 3.
기본적인 선언 방식
- 배열, 컬렉션(list, set, map)등을 스트림 형태로 만들기.
Stream<데이터타입> stream명 = Arrays.stream(배열명);
Stream<데이터타입> stream명 = 리스트명.stream();
Stream<데이터타입> stream명 = Stream.of('값','값'....)

람다식(함수적 스타일(functional - style) )으로 처리할 수 있도록 해주는 반복자

Stream은 데이터를 다루는데 자주 사용되어지는 메서드를 정의 해 놓은 Interface 입니다.

List<String> list = Arrays.asList("홍길동","홍길순","홍당무");
// 리스트 생성후 값 저장
Iterator<String> iterator = list.iterator();
// 반복자 생성
while(iterator.hasNext()) {
// 값이 있는 만큼 반복
	String name = iterator.next();
    // 값을 한개씩 가지고나옴
    System.out.println(name);
	}

이 코드가 아래 코드처럼 바뀔수 있는겁니다.

List<String> list = Arrays.asList("홍길동","홍길순","홍당무");
Stream<String> stream = list.stream();
stream.forEach(name -> System.out.println(name));

 

스트림은 Iterator와 비슷한 역할을 하는 반복자라고 할 수 있습니다.

람다식으로 요소 처리 코드를 제공합니다

- 대부분의 요소 처리 메서드는 함수적 인터페이스 매개 타입

스트림의 종류

- java.util.stream 패키지에 스트림 api 가 존재합니다.

BaseStream

= 모든 스트림에서 사용 가능한 공통 메서드입니다 (직접 사용은 불가능)

Stream - 객체 요소 처리

IntStream, LongStream, DoubleStream은 각각 기본 타입인 int , long, double 요소를 처리합니다.

리턴 타입 메소드(매게 변수)  
Stream<T> java.util.Collection.stream()
java.util.Collection.parallelStream()
컬렉션
Stream<T>
IntStream
LongStream
DoubleStream
Arrays.stream(T[]), Stream.of(T[])
Arrays.stream(int[]), IntStream.of(int[])
Arrays.stream(long[]), LongStream.of(long[])
Arrays.stream(double[]), DoubleStream.of(double[])




배열
IntStream intStream.range(int, int)
intStream.rangeClose(int, int)
int 범위
LongStream LongStream.range(long, long)
LongStream.rangeClose(long, long)
long 범위
Stream<Path> Files.find(Path, int, BiPredicate, FileVisitOption)
Files.list(Path)
디렉토리
Stream<String> Files.lines(Path, Charset) 파일
DoubleStream
IntStream
LongStream
Random.doubles(...)
Random.ints()
Random.longs()
랜덤수

List <Student> 컬렉션에서 Stream <Student>를 얻어내고 요소를 콘솔에 출력해 보겠습니다.

 

public class Student {
	// 필드생성
	private String name;
	private int score;
	// 생성자
	public Student (String name, int score) {
		this.name = name;
		this.score = score;
	}
	void 가 없으면 리턴값을 쓰자
	public String getName() { return name; }
	public int getScore() { return score; }
}

구현부 작성

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class FromCollectionEx {

	public static void main(String[] args) {
		List<Student> stList = Arrays.asList(
				new Student("홍길동", 10),
				new Student("홍길순", 20),
				new Student("홍당무", 30)
				); 
		Stream<Student> stream = stList.stream();
		stream.forEach(s -> System.out.println(s.getName()));
	}
	
 }

다음은 String []과 int [] 배열로부터 스트림일 얻어 내고 콘솔에 출력해보겠습니다.

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class FromArrayEx {

	public static void main(String[] args) {
		
		String[] strArray = {"홍길동","홍길순","홍당무"};
		Stream<String> strStream = Arrays.stream(strArray);
		strStream.forEach(a -> System.out.println(a + ","));
		System.out.println();
		
		int[] intArray = {1,2,3,4,5};
		IntStream intStream = Arrays.stream(intArray);
		intStream.forEach(a -> System.out.print(a + "."));
		System.out.println();
	}
	
 }

숫자 범위로부터 스트림 얻기

1~100까지의 합을 구해보겠습니다.

import java.util.stream.IntStream;

public class FromIntERangeEx {
	public static int sum;
	
	public static void main(String[] args) {
		// 1~100까지의 합구하기
		IntStream stream = IntStream.rangeClosed(1, 100);
		stream.forEach(a -> sum += a);
		System.out.println("총합 : " + sum);
		
		// 총합 : 5050 출력
	}
}

파일로부터 스트림 얻기

디음 예제는 Files의 정적 메서드인 lines ()와 BufferedReader의 lines () 메서드를

이용하여 문 자 파일의 내용을 스트림을 통해 행 단위로 읽고 콘솔에 출력한다.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class FromFileContentEx {

	public static void main(String[] args) throws IOException {
		Path path = Paths.get("src/linedata.txt");
		// 파일의 경로 정보를 가지고 있는 Path 객체 생성
		Stream<String> stream;
		
		// Files.lines() 메소드 이용
		stream = Files.lines(path, Charset.defaultCharset());
		// 운영체제의 기본 문자셋
		
		stream.forEach(System.out::println);
		// 메소드 참조(s -> System.out.println(s)와 같은방법)
		System.out.println(); 
		
		// BufferedReader의 lines() 메소드 이용
		File file = path.toFile();
		FileReader fileReader = new FileReader(file);
		BufferedReader br = new BufferedReader(fileReader);
		stream = br.lines();
		stream.forEach(System.out::println);
				

	}

}

다음은 Files의 정적 메서 도인 list()를 이용해서 디렉터리의 내용(서브 디렉터리 or 파일목록)을 스트림을 통해 읽고 콘솔에 출력하겠습니다.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class FromDirectoryEx {

	public static void main(String[] args) throws IOException {
		Path path = Paths.get("C:\\Users\\TJ\\eclipse-workspace\\JAVAST\\Stream\\src");
		Stream<Path> stream = Files.list(path);
		stream.forEach(p -> System.out.println(p.getFileName()));
		// p - 서브 디렉토리 또는 파일에 해당하는 Path 객체
		// p.getFileName() - 서브 디렉토리 이름 or 파일이름 리턴
	}

}

폴더 위치를 그냥 프로젝트 폴더로 저장했습니다.

출력 결과 -

 

스트림 파이프라인에서 중간 처리를 하는 메서드와 최종 처리를 하는 메서드의 종류를 살펴보기로 합시다.

다음은 스트림이 제공하는 중간 처리와 최종 처리를 하는 메서드를 성명하는 표입니다.

중간처리 메서드

최종 처리 메서드

중간처리 메서드와 최종 처리 메서드를  쉽게 구분하는 방법은 리턴 타입을 보면 됩니다. 리턴 타입이 스트림이라면 중간 처리 메서드이고 기본 타입이거나 OptionalXXX라면 최종 처리 메서드입니다. 소속된 인터페이스에서 공통의 의미는 

Stream, IntStream, LongStream, DoubleStream에서 모두 제공 가능하다는 뜻입니다.

 

필터링(distinct() , filter())

필터링은 중간 처리 기능으로 요소를 걸러내는 역할을 합니다. 필터링 메서드인 distinct()와 filter() 메서드는 모든 스트림이 가지고 있는 공통 메서드입니다.

distinct() 메서드는 중복을 제거하는데 Stream의 경우에는 Object, equlas(Object)가 true 이면 동일한

객체로 판단하고 중복을 제거합니다. IntStream, LongStream, DoubleStrea은 동일 값일 경우 중복 제거합니다.

 

예제 - 필터링

List 생성후 중복 이름은 제거하고 성이 "홍"인 이름만 필터링해서 출력해보겠습니다.

import java.util.Arrays;
import java.util.List;

public class FilteringEx {

	public static void main(String[] args) {
		List<String> name = Arrays.asList("홍길동 ","홍길순 ","김상식 ","홍삼 ","김판호 ","홍길동");
		System.out.println();
		
		name.stream().distinct() //중복을 제거한다
		.forEach(x -> System.out.print(x));
		System.out.println();
		
		name.stream() // 필터링
		.filter(x -> x.startsWith("김"))
		.forEach(x -> System.out.println(x));
		System.out.println();
		
		name.stream()
		.distinct() // 중복을 제거하고 필터링 해준다.
		.filter(x -> x.startsWith("김"))
		.forEach(x -> System.out.println(x));
	

	}

}

처음에 실수로 " " 도 문자열인데 생각 없이 중복 값에는 띄어쓰기를 안 해서 중복 인식하지 않아 값이 홍길동 2개씩 나왔는데 다들 조심하세요

'JAVA' 카테고리의 다른 글

Array 다차원 배열  (0) 2022.06.23
Arrary  (0) 2022.06.21
멀티 스레드  (0) 2022.06.02
Map 컬렉션  (0) 2022.05.31
컬렉션 프레임워크 Set 컬렉션  (0) 2022.05.30