개인용 복습공간

[Java] 스트림과 스트림을 이용한 입출력 본문

Java

[Java] 스트림과 스트림을 이용한 입출력

taehwanis 2021. 5. 18. 23:04

 

 

 

스트림과 스트림을 이용한
입출력 처리를 해보려 한다.

 

 

 

 

 

스트림

스트림은 데이터 집합체를 반복적으로 처리한다. 스트림을 이용하면 다수의 스레드 코드를 구현하지 않아도 데이터를 병렬로 처리할 수 있다. 스트림은 데이터와 스트림 연산의 개념을 모두 포함한다.

컬렉션이 데이터의 공간적 집합체라면, 스트림은 데이터의 시간적 집합체이다. 컬렉션은 데이터 원소의 효율적인 관리와 접근에 맞게 설계되어 있지만, 스트림은 데이터 원소에서 수행할 함수형 연산에 맞게 설계되어 있다. 그리고 스트림을 사용하면 코드가 간단해지고 오류 발생 확률이 줄어든다.

 

스트림과 컬렉션 비교 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
 
public class StreamDemoEx {
 
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        Random r = new Random();
        for(int i=0; i<10; i++)
            list.add(r.nextInt(30));
        
        //filter:>10,sort,출력
        
        //1) Collection 프레임웍크 사용방법
        List<Integer> gt10 = new ArrayList();
        for(int i:list)
            if(i>10) gt10.add(i);
        
        Collections.sort(gt10);
        System.out.println(gt10);
        
        //2.Stream 처리 방식
        list.stream().filter(i -> i>10).sorted().forEach(x -> System.out.print(x+" "));
 
    }
 
}
cs

 

 

 

스트림 종류
  • Stream (객체 스트림)
  • IntStream (숫자 스트림)
  • LongStream (숫자 스트림)
  • DoubleStream (숫자 스트림)

 

객체 스트림이 제공하는 최종 연산이 Optional 타입을 반환하고
숫자 스트림은 OptionalInt, OptionalLong, OptionalDouble 타입 반환한다.

 

 

 

스트림 생성

 

  • 컬렉션으로부터 스트림 생성
    default Stream stream()
    default Stream parallelStream()

  • 배열로부터 스트림 생성
    - Arrays 클래스가 제공
    static IntStream stream(int [] array)
    static IntStream of(int... values)
    - Stream 인터페이스가 제공
    static Stream of(T... values)
    - IntStream 인터페이스가 제공
    static IntStream of(int... values)

  • 기타 데이터로부터 스트림 생성
    - Random의 ints( ), longs( ), doubles( )
    - 숫자 스트림과 객체 스트림의 iterate( )와 generate( ), empty()
    - IntStream과 LongStream의 range( ) 혹은 rangeClosed( )
    - 입출력 파일이나 폴더로부터도 스트림을 생성

 

스트림 생성 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.util.Arrays;
import java.util.Random;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.Stream;
 
//스트림 생성 방식
public class GenerateStreamEx {
 
    public static void main(String[] args) {
        //배열로 부터 스트림 생성
        int[] ia = {1,3,5,7,9,11,13,15};
        
        IntStream is = Arrays.stream(ia);
        is.forEach(x -> System.out.print(x+ " "));
        
        System.out.println();
        
        //스트링 배열
        String[] sa = { "The""pen""is","mighter","than","the","sword"};
        Stream<String> ss = Stream.of(sa);
        ss.forEach(x -> System.out.print(x + " "));
        System.out.println();
        
        //Double 배열
        double[] da = {3.141.55.96.29.9};
        DoubleStream ds = DoubleStream.of(da);
        ds.forEach(x -> System.out.print(x + " "));
        System.out.println();
        
        IntStream is2 = IntStream.iterate(1, x -> x+2).limit(10);
        is2.forEach(x -> System.out.print(x + " "));
        
        System.out.println();
        IntStream is3 = new Random().ints(050).limit(10);
        is3.forEach(x -> System.out.print(x + " "));
        
        System.out.println();
        
        Stream<Double> ds2 = Stream.generate(Math::random).limit(10);
        ds2.forEach(x -> System.out.print(x +" "));
        
        System.out.println();
        IntStream is4 = IntStream.range(15);
        is4.forEach(x -> System.out.print(x + " "));
    }
 
}
 
cs

실행 화면

 

 

스트림 연산

스트림 연산의 결과가 Stream 타입이면 연속적으로 호출 가능하다. 스트림 연산의 연속 호출은 여러 개의 스트림이 연결되어 스트림 파이프라인을 형성한다.

스트림 파이프라인

스트림의 최종 연산조급한 연산이지만 중간 연산느긋한 연산이라 한다. 최종 연산이 호출되기 전까지 중간 연산은 아무런 작업을 수행하지 않는다.

멀티 코어 CPU를 제대로 활용하여 데이터 소스를 병렬로 처리할 수 있도록 병렬 스트림을 지원한다. 컬렉션 혹은 순차 스트림으로부터 각각 parallelStream( ) 혹은 parallel( ) 메서드를 호출하여 병렬 스트림을 획득한다. 스트림을 부분 스트림으로 분할하기 어렵거나 데이터 소스의 크기가 작거나 혹은 싱글 코어 CPU라면 오히려 성능이 나빠질 수 있다.

 

 

 

스트림 옵션 타입

Optional은 null을 사용하지 않고 부재 값을 포함한 데이터를 저장하는 클래스로써 값의 존재 여부에 따라 다양하게 처리할 수 있는 기능을 제공한다.

 

옵션 타입 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
 
public class OptionalEx {
   public static OptionalDouble divide(double x, double y) {
      return y==0 ? OptionalDouble.empty() : OptionalDouble.of(x/y);
   }
   
   public static void main(String[] args) {
      OptionalInt i = OptionalInt.of(100);
      OptionalDouble d = OptionalDouble.of(3.141592);
      Optional<String> s = Optional.of("Good Afternoon");
      
      System.out.println(i.getAsInt());
      System.out.println(d.getAsDouble());
      System.out.println(s.get());
      
      System.out.println(i);
      System.out.println(d);
      System.out.println(s);
      
      System.out.println(divide(1.02.0));
      System.out.println(divide(1.00.0));
      
      System.out.println("================================");   
      String s1 = "Stream Test"//1차 테스트
      Optional<String> so = Optional.ofNullable(s1);
      
      if(s1 != null) {
         System.out.println(s1);
      }else{
         System.out.println("없음");
      }
      
      if(so.isPresent()) {
         System.out.println(so.get());
      }else{
         System.out.println("없음");
      }
      
      String s2 = so.orElse("없음");
      System.out.println(s2);
      
      so.ifPresentOrElse(x -> System.out.println(x), () -> System.out.println("없음"));
   }
 
}
cs

실행 화면

 

 

 

 

스트림 활용

연산 종류는 여러 가지가 있다. 

  • 중간 연산 : 필터링 - filter(), 매핑 - map(), 정렬 - sorted()
  • 조급한 연산 : 매칭 - anyMatch(), 카운팅, 최대값, 최소값, 평균, 합계, 리듀싱 - reduce(), 수집/집계 - 컬렉터 연산,
    파티셔닝, 그룹핑

 

 

스트림활용은 나중에 다시 다뤄보려 한다.

 

 

 

스트림을 이용한 입출력

JAVA 7의 NIO가 JAVA 8의 스트림 기반과 결합하여 더욱더 막강해졌다.
NIO는 Path, Fils, FileSystem, WalkFileTree, walk, WatchService

 

스트림 얻기

BufferedReader 클래스의 lines() 메서드를 이용하면 스트림을 생성한다.
Files의 정적 메서드를 사용해 파일이나 폴더의 내용을 행 단위로 읽을 수 있는 스트림을 생성한다.

 

Files가 스트림을 반환하는 정적 메서드

  • Stream<String> lines(Path path) - 기본 문자 집합을 이용해 파일의 모든 행을 스트림으로 반환한다.
  • Stream<String> lines(Path path, Charset cs) - 주어진 문자집합을 이용해 파일의 모든 행을 스트림으로 반환한다.
  • Stream<Path> list(Path dir) - 서브 폴더를 제외한 폴더에 들어 있는 모든 원소를 스트림으로 변환한다.
  • Stream<Path> walk(Path start) - 서브 폴더를 포함한 폴더에 들어 있는 모든 원소를 스트림으로 반환한다.

 

스트림 얻기 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.io.File;
import java.util.Arrays;
import java.util.stream.Stream;
 
public class FileStreamEx {
 
   public static void main(String[] args) {
      File file = new File("c:/windows");
      File[] fs = file.listFiles();
      
      Stream<File> stream = Arrays.stream(fs);
      long count = stream.filter(x->x.isDirectory()==false).count();
      System.out.println("c:/windows에 있는 파일 개수 : " + count);
      
 
   }
 
}
cs

 

 

 

 

버퍼

NIO 기반의 데이터 입출력을 위해 사용되는 메모리 배열이다.
Buffer의 구현 클래스는 모두 특정 기초 타입을 지원하기 위한 것이다. (ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer 등)

 

Buffer 클래스의 주요 메서드

  • Object array() - 배열로 반환한다.
  • int capacity() - capacity 값을 반환한다.
  • Buffer clear() - position <- 0, limit <- capacity (데이터는 그대로 둔다.)
  • Buffer flip() - limit <- position, position <- 0
  • int limit() - limit 값을 반환한다.
  • int position() - position값을 반환한다. 인덱스 값으로 0부터 시작한다.
  • Buffer rewind() - position <- 0
  •  

Buffer 클래스 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.nio.ByteBuffer;
 
public class StreamIO3 {
    
    public StreamIO3() {
        ByteBuffer buf = ByteBuffer.allocate(10);
        System.out.println(buf);
        
        buf.put("ab".getBytes());
        System.out.println(buf);
        
        buf.put("cde".getBytes());
        System.out.println(buf);
        
        buf.flip();
        System.out.println(buf);
        
        System.out.println(new String(buf.array()));
        
        buf.clear();
        System.out.println(buf);
    }
 
 
    public static void main(String[] args) {
 
        new StreamIO3();
    }
}
cs
Comments