728x90

바이트기반 보조스트림

FilterInputStream, FilterOutputStream

FilterInputStream과 FilterOutputStream은 InputStream/OutputStream의 자손이면서 모든 보조스트림의 조상이다.

보조스트림은 자체적으로 입출력을 수행할 수 없기 때문에 기반 스트림을 필요로한다.

protected(FilterInputStream(InputStream in)

public FilterOutputStream(OutputStream out)

 

FilterI/OStream의 모든 메서드는 기반스트림의 메서드를 그대로 호출하고 Filter보조스트림은 아무런 일을 하지않는다. FilterInputStream, FilterOutputStream은 상속을 통해 원하는 작업을 수행하도록 읽고쓰는 메서드를 오버라이딩 해야한다.

 

FilterInputStream의 자손 BufferedInputStream, DataInputStream, PushbackInputStream 등

FilterOutputStream의 자손 BufferedOutputStream, DataOutputStream, PrintStream 등

 

BufferedInputStream, BufferedOutputStream

버퍼 보조스트림은 입출력의 효율을 높이기 위해 사용된다. 버퍼를 이용해서 한번에 여러 바이트를 입출력하는것이 빨라지기 떄문이다.

BufferedInputStream(InputStream in, int size) : InputStream인스턴스와 버퍼 사이즈를 지정하여 버퍼 InputStream을 생성한다.

BufferedInputStream(InputStream in) : InputStream인스턴스만을 인자로 넣어주며 버퍼의 사이즈를 지정해주지 않는경우 8192byte크기의 버퍼를 갖게된다.

 

BufferedInputStream은 입력소스로부터 데이터를 buffer크기만큼 데이터를 읽어 내부 버퍼에 저장해놓는다. 프로그램에서는 외부가 아닌 내부 버퍼에 저장된 데이터를 읽어들이기 때문에 효율적인 데이터 처리가 가능하다.

내부 버퍼에 저장된 모든 데이터를 읽어들인 이후 read메서드가 호출되면 BufferedInputStream은 입력 소스로부터 다시 버퍼크기만큼의 데이터를 읽어다 버퍼에 저장해 놓는다.

 

BufferedOutputStream(OutputStream out, int size) : OutputStream인스턴스와 버퍼 사이즈를 인자로 던져 내부버퍼를 갖는 BufferedOutputStream 인스턴스를 생성한다.

BufferedOutputStream(OutputStream out) : OutputStream인스턴스를 인자로 주며 사이즈를 지정해주지 않을 경우 기본 버퍼사이즈는 8192byte크기가 된다.

flush() : 버퍼의 모든 내용을 출력하여 버퍼를 비운다.

close() : flush()를 호출해서 버퍼의 모든 내용을 출력하고 BufferedOutputStream인스턴스가 사용하던 모든 자원을 반환한다.

 

BufferedOutputStream 도 버퍼를 이용하여 출력작업을 하게 된다. write()메소드를 이용하여 BufferedOutputStream의 데이터를 내부 버퍼에 복사하고 버퍼로부터 출력한다. 버퍼의 모든내용을 출력한 후 write()호출 시 버퍼를 비우고 추가적인 데이터들을 내부 버퍼에 복사한다. 

출력소스가 버퍼에 남아있는 채로 프로그램이 종료될 수 있기 때문에, BufferedOutputStream을 사용완료한 후에는 반드시 BufferedOutputStream의 close()메소드나 flush() 메소드를 호출해 버퍼의 모든내용이 출력되도록 해야한다.

버퍼의 사이즈가 5기때문에 처음 write호출시 1부터 5까지만 write되고 6,7,8,9는 버퍼에 존재한다.

버퍼를 비우기위해 bos.close()를 호출하여 버퍼에 존재하는 6,7,8,9가 출력되고 버퍼를 비운다.

 

DataInputStream, DataOutputStream

DataInputStream은 FilterInputStream의 자손이며 DataInput인터페이스를 구현한 클래스이다.

DataOutputStream은 FilterOutputStream의 자손이며 DataOutput인터페이스를 구현한 클래스이다.

DataStream을 사용하면 byte뿐만아니라 8가지 기본 자료형의 값들도 읽기,쓰기가 가능하다. DataStream을 이용하여 기본 자료형 값을 출력한경우 이값을 읽기위해서는 똑같이 DataStream의 기본자료형을 이용해야한다.

sample.dat파일을 HxD로 열었을 경우이다. 4바이트중 10의 16진수인 A가 출력되고 20.0f가 4바이트로 41A00000이 저장되어있다. 마지막으로 ture값인 1이 저장된것을 알 수 있다.

 

 

sample.dat파일을 각각 기본자료형으로 읽어 출력하는 프로그램이다.

DataOutputStream으로 저장한 데이터 기본자료형에 맞추어 read를 해주면 정상적으로 파일을 읽을 수 있다.

데이터를 변환없이 저장하고 읽을때 사용하면 편하다.

 

try내부에서 파일을 while(true)로 계속해서 읽는다. 파일의 끝에 도달하여 read를 하면 EOFException이 발생하여 sum을 출력하고 try-catch부분이 끝나는경우 finally의 close()가 실행되어 스트림을 모두 비워준다. 

 

JDK1.7이후부터 try-with-resource문을 이용하여 close()를 호출하지 않아도 자동호출되도록 할 수 있다.

위처럼 try의 내부()에 자원을 적어주는것이 try-with-resources문이다. 위처럼 처리해줄경우 close()를 직접 호출하지않아도 ()내부의 자원이 자동으로 close()된다.

 

SequenceInputStream

입력스트림을 연속적으로 연결해서 하나의 스트림으로부터 데이터를 읽을 수 있는것

SequenceInputStream(Enumeration e) : 저장된 입력스트림을 하나의 스트림으료 연결한다.

SequenceInputStream(InputStream s1, InputStream s2) : 두개의 입력스트림을 하나로 연결한다.

 

위처럼 사용할 수 있다.

 

728x90

'Programming > JAVA' 카테고리의 다른 글

바이트 기반 스트림  (0) 2021.09.10
자바의 입출력  (0) 2021.09.10
그룹화와 분할 - groupingBy(), partitioningBy()  (0) 2021.09.02
collect()  (0) 2021.09.02
스트림의 최종연산  (0) 2021.09.01
728x90

바이트 기반 스트림

InputStream과 OutputStream

InputStream의 메서드

int available() : 스트림으로부터 읽어 올 수 있는 데이터의 크기를 반환한다.

void close() : 스트림을 닫음으로써 사용하고 있던 자원을 반환한다.

void mark(int readlimit) : 현재위치를 표시해 놓는다. 후에 reset()에 의해서 표시해 놓은 위치로 다시 돌아갈 수 있다. readlimit은 되돌아갈 수 있는 byte의 수이다.

boolean markSupported() : mark()와 reset()을 지원하는지 알려준다.

abstract int read() : 1byte를 읽어온다. 더이상 읽어올 데이터가 없으면 -1을 반환한다.

int read(byte[] b) : 배열 b의 크기만큼 읽어서 배열을 채우고 읽어온 데이터 수를 반환한다.

int read(byte[] b, int off, int len) : len개의 byte를 읽어서, 배열 b의 지정된 위치(off)부터 저장한다. 실제로 읽어오는 데이터의 수는 len보다 작을 수 있다.

void reset() : 스트림에서의 위치(offset)를 마지막으로 mark()이 호출되었던 위치로 되돌린다.

long skip(long n) : 스트림에서 주어진 길이(n)만큼을 건너뛴다.

 

OutputStream 메서드

void close() : 입력소스를 닫음으로써 사용하고 있던 자원을 반환한다.

void flush() : 스트림의 버퍼에있는 모든 내용을 출력소스에 쓴다.

abstract void write(int b) : 주어진 값을 출력소스에 쓴다.

void write(byte[ ] b) : 주어진 배열 b에 저장된 모든 내용을 출력소스에 쓴다.

void write(byte[ ] b, int off, int len) : 주어진 배열 b에 저장된 내용 중에서 off번째부터 len개 만큼만을 읽어서 출력소스에 쓴다.

 

flush()는 버퍼가 있는 출력스트림에서만 의미가 있다. 

프로그램이 종료될 때, 사용하고 close하지 않은 스트림을 JVM이 자동적으로 닫아주기는 하지만 스트림을 사용 완료한 이후에는 close()를 호출하여 반드시 닫아주는 것이 좋다. 

ByteArrayInputStream처럼 메모리를 사용하는 스트림, System.in, System.out과 같은 표준 입출력 스트림은 닫아주지 않아도 된다.

 

ByteArrayInputStream과 ByteArrayOutput

바이트배열에 데이터를 입출력하는데 사용되는 스트림이다. 입출력하기 전에 데이터를 임시로 바이트배열에 담아서 변환 등의 작업을 하는데 사용된다.

스트림의 종류가 달라도 읽고 쓰는 방법은 동일하다.

 

ByteArrayInputStream()에 읽을 데이터를 매개변수로 주어 읽기 스트림을 주고 ByteArrayOutputStream을 생성해주어 각InputStream에 저장된 데이터를 하나씩 입력받아 출력 스트림에 쓴다. 이후 스트림에 적은내용을 배열에 옮긴다.

배열을 스트림을 통해 복사하는 방법이다.

 

배열 크기 복사

InputStream의 offset 0부터 temp.length만큼 데이터를 읽어 temp에 저장한다.

이후 temp에 저장된 내용을 temp의 offset 5부터 길이 5만큼 outputStream에 쓴다.

available()을 통해 스트림에 읽을 데이터가 남아있는경우 반복문이 계속 실행되게하고 내부에서는 데이터를 temp의 크기(4byte)만큼씩 temp에 저장하고 output.write를 통해 temp 에 저장된 데이터를 outputStream에 temp크기만큼씩 쓴다.

tmep의 마지막 저장결과를 보면 4바이트씩 읽다가 마지막에 입력스트림에 2바이트밖에 남지않아 2바이트를 읽은 경우이다. 기존의 데이터를 가지고있는상태에서 2바이만 새로읽어 뒷내용이 유지된다. 이후 OutputStream의 결과처럼 temp의 모든내용이 저장된다.

 

위의 예제에서의 temp에서 저장된 데이터가 변하지 않는 문제점을 해결한 예제이다. 읽은 크기만큼만 write하기 때문에 마지막에 2byte를 읽은경우 2byte만 write하여 배열이 그대로 복사된다.

728x90

'Programming > JAVA' 카테고리의 다른 글

바이트기반 보조스트림  (0) 2021.09.11
자바의 입출력  (0) 2021.09.10
그룹화와 분할 - groupingBy(), partitioningBy()  (0) 2021.09.02
collect()  (0) 2021.09.02
스트림의 최종연산  (0) 2021.09.01
728x90

입출력

입출력 : I/O Input과 Output의 약자이다. 컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고받는 것을 의미한다. 키보드로부터 입력을 받고 모니터 화면에 출력을 하는 행위도 I/O행위이다.

 

스트림(Stream)

자바에서의 입출력 즉 데이터를 한쪽에서 다른쪽으로 전달하려면 두 개의 대상을 연결하고 데이터를 전송할 수 있는 것이 필요하다. 이것을 스트림(Stream)이라한다.

이전에 작성한 스트림과는 다른 개념이다.

 

입출력에서 사용되는 스트림은 데이터를 운반하는 연결통로를 의미한다.

 

스트림은 한쪽방향 즉 단방향 통신만 가능하다. 그렇기 때문에 입력과 출력을 수행하기 위해서는 입력스트림(input Stream), 출력스트림(output stream) 2개의 스트림이 각각 필요하다.

 

스트림은 먼저보낸 데이터를 먼저 받는 FIFO 구조이다. 중간에 건너뜀 없이 연속적으로 데이터를 주고 받는다.

 

바이트기반 스트림 InputStream, OutputStream

스트림은 바이트단위로 데이터를 전송하며 입출력 대상에 따라 다른 스트림을 사용한다.

파일

입력스트림 - FileInputStream

출력스트림 - FileOutputStream

메모리(byte 배열)

입력스트림 - ByteArrayInputStream

출력스트림 - ByteArrayOutputStream

프로세스(프로세스간 통신)

입력스트림 - PipedInputStream

출력스트림 - PipedOutputStream

오디오 장치

입력스트림 - AudioInputStream

출력스트림 - AudioOutputStream

 

입출력 대상에따라 입출력스트림 클래스가 정의되어있으며 각각 읽고 쓰는데 필요한 추상메서드들을 입출력대상에 맞게 구현해 놓았다.

 

읽기 쓰기 메서드

입력을 받는 InputStream에는 데이터를 읽는 read()메서드가 정의되어있다.

abstract int read()

int read(byte[] b)

int read(byte[] b, int off, int len)

 

int read(byte[] b) 메서드는 내부적으로 int read(byte[] b, int off, int len) 를 호출하고  int read(byte[] b, int off, int len) 는 내부적으로 read()를 호출한다. 추상메서드 read() 는 입력스트림으로 부터 1byte를 읽어서 반환하는 메서드로 구현되어있다.

 

출력 스트림 OutputStream에는 데이터를 출력하는 write()메서드가 정의되어있다.

abstract void write(int b)

void write(byte [] b)

void write(byte[] b, int off, int len)

 

write()메서드도 마찬가지로 아래 두개의 메서드가 내부적으로 write(int b)를 사용한다.

write(int b)는 b를 출력하는 함수이다. 각각 데이터를 출력스트림으로 출력한다.

 

보조스트림

스트림의 기능을 보완하기 위한 보조스트림이 제공된다. 보조스트림은 데이터를 입출력하는것이아닌 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있는 역할을 한다. 보조스트림을 사용하기위해서는 입출력 스트림을 먼저 생성한 후 이것을 이용하여 보조스트림을 생성해야한다.

 

FileInputStream fis = new FileInputStream("test.txt");

BufferedInputStream bis = new BufferedInputStream(fis);

bis.read();

 

test파일을 읽는 코드이다.

파일 입력 스트림인 FileInputStream에 성능 향상을 위한 보조스트림 BufferedInputStream을 생성해준 경우이다. 보조스트림역시 InputStream과 OutputStream의 자손이므로 입출력방법이 동일하다.

 

보조스트림의 종류

FilterInputStream, FilterOutputStream : 필터를 이용한 입출력 처리

BufferedInputStream. BufferedOutputStream : 버퍼를 이용한 입출력 처리

DataInputStream, DataOutputStream : int, float와 같은 기본형 단위(primitive type)로 데이터를 처리하는 기능

SequenceInputStream : 두개의 데이터를 하나로 연결

LineNumberInputStream : 읽어 온 데이터의 라인 번호를 카운트

ObjectInputStream, ObjectOutputStream : 데이터를 객체단위로 읽고 쓰는데 사용. 주로 파일을 이용하며 객체 직렬화

PrintStream : 버퍼를 이용하며, 추가적인 print관련 기능

PushbackInputStream : 버퍼를 이ㅛㅇ해서 읽어온 데이터를 다시 되돌리는 기능(unread, push back to buffer)

 

문자기반 스트림 Reader, Writer

자바에서는 문자형인 char형이 2byte이기 때문에 바이트 기반의 스트림으로 2byte인 문자를 처리하는데 어려움이 있다.

2byte문자를 처리하기 위한 스트림이 문자기반 스트림 Reader와 Writer이다.

문자데이터를 입출력 할때는 바이트기반 스트림 대신 문자기반 스트림을 사용하는것이 좋다.

 

문자열 파일

입력스트림 - FileReader

출력스트림 - FileWriter

문자열 메모리(char 배열)

입력스트림 - CharArrayReader

출력스트림 - CharArrayWriter

프로세스(프로세스간 문자열 통신)

입력스트림 - PipedReader

출력스트림 - PipedWriter

문자열 버퍼 스트림

입력스트림 - StringReader

출력스트림 - StringWriter

 

Reader메서드

int read()

int read(char[] cbuf)

abstract int read(char[] cbuf, int off, int len)

 

InputStream의 read와 비슷하지만 Reader의 read()는 char배열을 인자로받아 처리한다.

 

Writer메서드

void write(int c)

void write(char[] cbuf)

abstract void write(char[] cbuf, int off, int len)

void write(String str)

void write(String str, int off, int len)

 

Writer의 write메서드의 인자로 char[]과 String을 받아서 처리한다.

 

문자열 기반 보조스트림

BufferedReader, BufferedWriter : 문자열기반 버퍼를 사용한다.

FilterReader, FilterWriter : 문자열기반 필터를 사용한다.

LineNumberReader : 읽어온 문자 데이터 라인 번호를 카운트한다.

PrintWriter : 버퍼를 이용하여, 추가적인 출력기능

pushbackReader : 버퍼를 이용해서 읽어온 읽어온 데이터를 다시 되돌린다.

 

728x90

'Programming > JAVA' 카테고리의 다른 글

바이트기반 보조스트림  (0) 2021.09.11
바이트 기반 스트림  (0) 2021.09.10
그룹화와 분할 - groupingBy(), partitioningBy()  (0) 2021.09.02
collect()  (0) 2021.09.02
스트림의 최종연산  (0) 2021.09.01
728x90

그룹화와 분할

그룹화 : 스트림의 요소를 특정 기준으로 그룹화 하는것

분할 : 스트림의 요소를 두가지, 지정한 조건에 일치하는 그룹과 일치하지 않는 그룹으로 분할하는것

 

그룹화 메서드 groupingBy()

Collector groupingBy(Function classifier)

Collector groupingBy(Function classifier, Collecctor downstream)

Collector grooupingBy(Function classifier, Supplier mapFactory, Collector downstream)

 

분할 메서드 partitioningBy()

Collector partitioningBy(Predicate predicate)

Collector partitioningBy(Predicate predicate, Collecctor downstream)

 

그룹화인 groupingBy()의 경우 Function을 매개변수로 받고 분할인 partitioningBy()의 경우 Predicate를 매개변수로 받는다. 스트림을 두개의 그룹으로 나눠야하는 경우 partitioningBy()가 더 빠르다.

그룹화와 분할의 결과는 Map에 담겨 반환된다.

 

partitioningBy()에 의한 분류

위처럼 코드가 있을경우 partitioningBy() 사용예시이다.

Map<Boolean, List<Student>> stuBySex = stuStream.collect(partitioningBy(Student::isMale));

List<Student> maleStudent = stuBySex.get(true);

List<Student> femaleStudent = stuBySex.get(flase);

각각 남자학생일경우, 여학생일 경우 List이다. Student객체에 boolean으로 초기화 되어있는 값을 확인하여 partitioningBy에서 분할한다.

 

성별 학생수 구하기

Map<Boolean, Long> stuNumBySex = stuStream.collect(partitioningBy(Student::isMale, counting());

System.out.println("남학생 수 : "+ stuNmBySex.get(true));

System.out.println("여학생 수 : "+ stuNmBySex.get(false));

 

성별 1등학생 구하기

Map<Boolean, Optional<Stuudent>> topScoreBySex = stuStream

                                       .collect(partitioningBy(Student::isMale,maxBy(comparingInt(Student::getScore)));

System.out.println("남학생 수 : "+ topScoreBySex.get(true));

System.out.println("여학생 수 : "+ topScoreBySex.get(false));

 

150점 아래 학생들만 출력

Map<Boolean, Map<Boolean, List<Student>>> failedStuBySex = stuStream

                      .collect(partitioningBy(Student::isMale, partitioningBy(s -> s.getScore() < 150)));

List<Student> failedMaleStu = failedStuBySex.get(true).get(true);

List<Student> failedFemaleStu = failedStuBySex.get(false).get(true);

 

groupingBy()에 의한 분류

학생들을 반별로 그룹짓기

Map<Integer, List<Student>> stuByBan = stuStream.collect(groupingBy(Student::getBan));

 

groupingBy()로 그룹화를 하면 기본적으로 List<T>에 값을 담는다.

toList()를 매개변수로 넣어주어도되고 필요에 따라 toSet()이나 toCollection(HashSet::new) 등을 사용할 수 있다.

ex)

Map<Integer, List<Student>> stuuByBan = stuStream.collect(groupingBy(Student::getBan, toList()));

Map<Integer, HashSet<Student>> stuByHak = stuStream

                                            .collect(groupingBy(Studuent::getHak,toCollection(HashSet::new)));

분할과 그룹화는 많이써봐야할것같다. 이해는 되지만 사용하지않은 상황에서 응용이 어렵게 느껴진다.

728x90

'Programming > JAVA' 카테고리의 다른 글

바이트 기반 스트림  (0) 2021.09.10
자바의 입출력  (0) 2021.09.10
collect()  (0) 2021.09.02
스트림의 최종연산  (0) 2021.09.01
Optional  (0) 2021.08.25
728x90

collect() 

collect()는 스트림의 요소를 수집하는 최종연산이다.

collect에는 어떻게 수집할 것인가에 대한 방법이 필요하는데 이러한 방법을 정의한것이 컬렉터(collector)이다.

 

컬렉터는 Collector 인터페이스를 구현한 것으로, 직접 구현하거나 미리 작성된 것을 사용할 수 있다. 

Collectors클래스는 미리 작성된 다양한 컬렉터를 반환하는 static메서드를 가지고 있다.

 

스트림의 요소를 수집하는 collect()의 매개변수로는 수집하는 방법인 컬렉터가 사용된다.

해당 컬렉터는 Collector 인터페이스를 통해 구현하거나, Collectors클래스의 static메서드를 통해 얻을 수 있다.

 

collect() : 스트림의 최종연산, 매개변수로 컬렉터가 필요하다.

Collector : 인터페이스로 컬렉터를 구현할 때 사용한다.

Collectors : 클래스이다. 미리작성된 static메서드로 컬렉터를 제공한다.

 

collect() 선언

Object collect(Collector collector) //Collector인터페이스를 구현한 객체를 매개변수로 사용한다.

Object collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)

 

스트림을 컬렉션과 배열로 변환 - toList(), toSet(), toMap(), toCollection(), toArray()

스트림의 모든 요소들을  컬렉션에 수집하기 위한 메서드들이다.

List<String> names = stuStream.map(Student::getName).collect(Collectors.toList());

Student스트림의 모든 요소들의 이름을 List로 수집한 코드이다.

 

ArrayList<String> list = names.stream().collect(Collectors.toCollection(ArrayList::new));

List<String>을 ArrayList로 할당한 코드이다.

List나 Set은 toList(), toSet()이 있지만 다른 컬렉션을 사용하고 싶은 경우 Collectors의 toCollection()에 해당 컬렉션 생성자를 넣어주면 가능하다.

 

toMap()

Map<String, Person> map = personStream.collect(Collectors.toMap(p->p.getRegId(), p->p));

toMap의 경우 key와 value를 각각 지정해 주어야한다.

 

스트림에 지정된 요소들을 배열로 저장하는 메서드 toArray()

toArray()에 매개변수로 해당 타입의 생성자 참조를 넣어주어야한다. 매개변수를 작성하지 않을시 반환되는 배열의 타입은 Object[] 이다.

Student[] stuNames = studentStream.toArray(Student[]::new);

Object[] stuNames = studentStream.toArray();

 

통계 - counting(), summingInt(), averagingInt(), maxBy(), minBy()

개수, 합, 평균, 최대값, 최솟값등을 반환하는 메서드이다.

 

ex)

long count = stuStream.count();

long count = stuStream.collect(Collectors.counting());

 

long totalScore = stuStream.mapToInt(Student::getTotalScore).sum();

long totalScore = stuStream.collect(summingInt(Student::getTotalScore));

 

OptionalInt topScore = studentStream.mapToInt(Student::getTotalScore).max();

Optional<Student> topStudent = stuStream.max(Comparator.comparingInt(Student::getTotalScore));

Optional<Student> topStudent = stuStream.collect(maxBy(Comparator.comparingInt(Student::getTotalScore));

 

IntSummaryStatics stat = stuStream.mapToInt(Student::getTotalScore).summaryStatistics();

IntSummaryStatics stat = stuStream.collect(summarizingInt(Student::getTotalScore));

 

위 예시는 collect를 사용한경우와 사용하지않은 경우를 비교한 것이다. collect사용법으로 알아두면 좋을것 같다.

 

리듀싱 - reducing()

리듀싱 선언

Collector reducing(BinaryOperator<T> op)

Collector reducing(T identity, BinaryOperator<T> op)

Collector reducing(U identity, Function<T, U> mapper, BinaryOperator<U> op)

 

사용예시

IntStream intStream = new Random().ints(1,46).distinct().limit(6);

 

OptionalInt max = intStream.reduce(Integer::max);

Optional<Integer> max = intStream.boxed().collect(reducing(Intger::max));

//intStream을 boxed()를 통해 Stream<Integer>로 변경한다.그래야 Stream에 선언된 collect를 사용할 수 있다.

 

long sum = intStream.reduce(0, (a,b) -> a+b);

long sum = intStream.boxed().collect(reducing(0,(a,b)->a+b));

 

int grandTotal = stuStream.map(Student::getTotalScore).reduce(0, Integer::sum);

int grandTotal = stuStream.collect(reducing(0, Student::getTotalScore, Integer::sum));

 

문자열 결합 - joining()

스트림의 모든요소를 하나의 문자열로 결합하여 반환한다. 구분자 지정및 접두사, 접미사 지정도 가능하다.

스트림의 요소가 문자열이 아닌경우에는 map()을 통해 문자열로 변환해주어야한다.

 

ex))

String studentNames = stuStream.map(Student::getName).collect(joining());

String studentNames = stuStream.map(Student::getName).collect(joining(","));

String studentNames = stuStream.map(Studednt::getName).collect(joining(",","[","]");

 

728x90

'Programming > JAVA' 카테고리의 다른 글

자바의 입출력  (0) 2021.09.10
그룹화와 분할 - groupingBy(), partitioningBy()  (0) 2021.09.02
스트림의 최종연산  (0) 2021.09.01
Optional  (0) 2021.08.25
스트림(Stream)의 중간연산  (0) 2021.08.25
728x90

스트림의 최종연산

스트림을 다루는데 중간연산과 최종연산이 사용된다.

최종 연산의 경우 스트림의 요소를 소모해서 결과를 만들어내기 때문에 최종연산 이후 스트림은 없어진다.

 

forEach()

void forEach(Consumer<? super T> action)

반환타입이 void이며 스트림의 요소들을 출력하는 용도로 많이 사용되는 최종연산이다.

 

allMatch(), anyMatch(), noneMatch(), findFirst(), findAny() - 조건검사

지정한 조건에 일치하는 스트림 요소가 있는지, 조건에 모두 일치하는지, 조건에 모두 일치하지 않는지 등을 확인하는데 사용되는 최종연산이다.

 

boolean allMatch(Predicate <? super T> predicate) : 조건식에 모든 요소가 일치하면 true반환

boolean anyMatch(Predicate <? super T> predicate) : 어떤 요소하나라도 조건에 일치하면 true반환

boolean noneMatch(Predicate<? super T> predicate) : 조건식에 모든 요소들이 일치하지 않는다면 true반환

 

filter()연산과 함께 사용되는 findFirst(), findAny()가 있다.

filter()를 적용하여 조건식에 맞는 요소가 있는지 확인할 때 사용한다.

findAny와 findFirst()는 반환 타입이 Optional<T>이며, 스트림의 요소가 없을 때는 비어있는 Optional 객체를 반환한다.

 

count(), sum(), average(), max(), min() - 통계

스트림의 요소들의 통계에 대한 정보를 얻을 수 있는 연산이다. 요소의 개수, 요소들의 합, 평균, 가장큰값, 가장 작은 값 등을 얻을 수 있다.

long count()

Optional<T> max(Comparator<? super T> comparator)

Optional<T> min(Comparator<? super T> comparator)

 

리듀싱 - reduce()

스트림의 요소를 하나씩 줄여나가면서 연산을 수행하고 모든 요소들을 소모하여 나온 결과를 반환한다.

Optional<T> reduce(BinaryOperator<T> accumulator)

두가지 요소를 연산하여 결과를 반환한다.

 

T reduce(T identity, BinaryOperator<T> accumulator)

-> 초기값(identity)를 가지고 연산(accumulator)를 수행한다.

U reduce(U identity, accumulator, BinaryOperator<U> combiner)

->combiner는 병렬 스트림에 의해 처리된 결과를 합할 때 사용한다.

 

reduce 사용예시

int count = intStream.reduce(0, (a,b)-> a+1);

int sum = intStream.reduce(0,(a,b)->a+b);

int max = intStream.reduce(Integer.MIN_VALUE, (a,b) -> a>b ? a: b);

int min = intStream.reduce(Integer.MAX_VALUE, (a,b) -> a < b? a:b);

 

a에 초기값이 대입되고 스트림요소들이 차례대로 b에 대입된다. 이후 연산결과가 a에 대입되며 b에 새로운요소가 들어오게된다.

최종연산 count()와 sum()의 경우 내부적으로 reduce()를 사용한다.

 

reduce의 반환타입은 Optional이다. IntStream의 reduce의 경우 반환 타입이 OptionalInt이다. 

OptionalInt에 저장된 값을 꺼낼때는 getAsInt()메서드를 사용하면된다.

ex)

OptionalInt max = intStream.reduce(Integer::max);

int maxValue = max.getAsInt();

 

 

728x90

'Programming > JAVA' 카테고리의 다른 글

그룹화와 분할 - groupingBy(), partitioningBy()  (0) 2021.09.02
collect()  (0) 2021.09.02
Optional  (0) 2021.08.25
스트림(Stream)의 중간연산  (0) 2021.08.25
스트림(Stream)  (0) 2021.08.24
728x90

Stream의 최종연산 결과가 종종 Optional타입인 경우가 있다.

Optional은 Stream의 최종연산결과를 다룰때 사용된다.

Optional<T>는 T타입의 객체 를 감싸는 래퍼 클래스이다. Optional타입의 객체에는 모든 타입의 참조변수를 담을 수 있다.

 

public final class Optional<T>

{

     private final T value;

      ...

}

 

Optional타입의 객체로 최종연산의 결과를 반환하는경우 Optional객체에 결과를 담아서 반환하는 것이다.

Optional객체의 경우 null을 결과로 받더라도 NullPointerException을 발생시키지 않아 유용하다.

 

Optional객체 생성

Optional객체를 생성할 때는 of() 또는 ofNullalble()을 사용한다.

ex)

String str = "abc";

Optional<String> optVal = Optional.of(str);

Optional<String> optVal = Optional.of("abc");

Optional<String> optVal = Optional.of(new String("abc"));

 

참조변수가 null일 가능성이있다면 of()대신 ofNullable()을 사용해야한다.

of()의경우 NullPointerException을 발생시키기 때문이다.

 

Optional객체 값 가져오기

get() : Optional 객체에 저장된 값을 가져올 때 사용하는 메서드이다.

orElse() : 값이 null일 경우 NoSuchElementException이 발생하는데 이것을 방지하기 위한 메서드

T orElseGet(Supplier<? extends T> other) : null을 대체할 값을 반환하는 람다식을 지정할 수 있다.

T orElseThrow(Supplier<? extends X> exceptionSupplier) : null일 때 지정된 예외를 발생시킬 수 있다.

 

Optional객체도 filter(), map(), flatMap()을 사용할 수 있다. 단 Optional의 map, flatMap의 반환 타입은 Stream이 아닌 Optional이다. 

 

isPresent()는 Optional객체의 값이 null이면 false를, 아니면 true를 반환한다.

 

Optional<T>를 반환하는 메서드 목록

Optional<T> findAny()

Optional<T> findFirst()

Optional<T> max(Comparator<? super T> comparator)

Optional<T> min(Comparator<? super T> comparator)

Optional<T> reduce(BinaryOperator<T> accumulator)

 

Optional 기본형

OptionalInt, OptionalLong, OptionalDouble로 각 기본형을 다루는 Optional들이 있다.

 

IntStream 에 정의된 메서드 목록

OptionalInt findAny()

OptionalInt findFirst()

OptionalInt reduce(IntBinaryOperator op)

OptionalInt max()

OptionalInt min()

OptionalDouble average()

 

 

Optional을 다루는 예제이다.

728x90

'Programming > JAVA' 카테고리의 다른 글

collect()  (0) 2021.09.02
스트림의 최종연산  (0) 2021.09.01
스트림(Stream)의 중간연산  (0) 2021.08.25
스트림(Stream)  (0) 2021.08.24
다양한 함수형 인터페이스 & 메서드 참조  (0) 2021.08.22
728x90

스트림의 중간연산

스트림 자르기 - skip(), limit()

skip()메서드와 limit()메서드는 스트림을 자르는데 사용한다.

Stream<T> skip(long n) : 스트림의 요소 처음부터 n개만큼 삭제한다.

Stream<T> limit(long maxSize) : 스트림의 요소중 maxSize만 남기고 제거한다.

 

스트림의 요소 걸러내기 - filter(), distinct()

Stream<T> filter(Predicate<? super T> predicate) : 주어진 조건(Predicate)에 해당하지않는 요소들을 제거한다.

Stream<T> distinct() : 중복되는 요소들을 제거하여 하나만 남긴다.

 

정렬 - sorted()

스트림을 정렬할 때 사용하는 sorted()메서드 이다.

Stream<T> sorted()

Stream<T> sorted(Comparator<? super T> comparator)

 

sorted()메서드는 매개변수로 주어지는 Comparator로 스트림을 정렬한다. Comparator를 지정하지않으면 스트림 요소의 기본 정렬 기준으로 정렬된다.

 

주어진 Student스트림을 정렬하는 예제이다. Ban을 기준으로 정렬하고 naturalOrder()를 통해 클래스에 정의된 compareTo 기준(totalScore)으로 정렬한다. 이후 각각 값들을 하나씩 출력한다.

변환 - map()

map() : 스트림에 저장된 값중 원하는 필드만 뽑아내거나 특정 형태로 변환해야 할 때 사용하는 메소드이다.

Stream<R> map(Function<? super T, ? extends R> mapper)

map()은 중간연산이기 때문에 filenameStream을 보면 최종연산으로 forEach를 사용한다.

fileStream을 보면 map(File::getName)을 통해 Stream<String>으로 변경하고, filter를 통해 확장자가 있는지 확인한다.

이후 확장자만 잘라내기위해 .이후의 값들을 확인. ->모든 확장자 글자들을 대문자로 변경 -> 중복제거 -> 출력 순으로 진행한다.

조회 - peek()

중간연산으로 연산중 결과를 확인할 수 있는 메서드이다.

연산사이에 삽입하여 연산의 결과가 올바르게 나왔는지 확인 가능하다.

중간연산 사이에 filename과 extension을 출력하여 결과를 확인한다.

Stream의 연산의경우 최종연산이 호출되면 중간연산들을 수행하기때문에 하나씩 출력된다.

 

mapToInt(), mapToLong(), mapToDouble()

map()은 연산의 결과로 Stream<T> 타입의 스트림을 반환하는데, 스트림의 요소를 숫자로 변환하는 경우 IntStream과 같은 기본형 스트림으로 변환하는것이 더 유용하다.

기본형 스트림으로 변환하기 위한 메서드들이다.

IntStream mapToInt(ToIntFunction<? super T> mapper);

DoubleStream mapToDouble(ToDoubleFunction <? super T> mapper);

LongStream mapToLong(ToLongFunction<? super T> mapper)

 

IntStream과 같은 기본형 스트림의 메서드

int sum() : 스트림의 모든요소의 합

OptionalDouble average() : sum() / (double)count()

OptionalInt max() : 스트림 요소중 최대값

OptionalInt min() : 스트림 요소중 최소값

 

sum()이나 average()같은 메소드들은 최종연산이기 때문에 한번 호출할경우 스트림이 닫힌다.

연속적으로 해당 메서드들을 호출해야할 경우 summaryStatistics()메서드를 통해서 IntSummaryStatistics형 자료를 따로 생성해주는것이 좋다.

IntStream을 통해 SummaryStatistics()를 호출할 경우 위처럼 getSum(), getAverage()등을 연속적으로 호출이 가능하다.

flatMap() - Stream<T[]>를 Stream<T>로 변환

스트림의 요소가 배열이거나 map()의 연산결과가 배열인 경우 스트림의 타입이 Stream<T[ ]>으로 생성된다.

이러한 경우 Stream<T>로 다루는것이 더 편한데, 이러한 경우 map()이 아닌 flatMap()을 사용해주면 된다.

flatMap을 통해 하나의 스트림으로 정리된것을 알 수 있다.

728x90

'Programming > JAVA' 카테고리의 다른 글

스트림의 최종연산  (0) 2021.09.01
Optional  (0) 2021.08.25
스트림(Stream)  (0) 2021.08.24
다양한 함수형 인터페이스 & 메서드 참조  (0) 2021.08.22
람다식(Lambda expression)  (0) 2021.08.21

+ Recent posts