nme.kr

Ch.16 스트림

스트림 소개

package chapter16;

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

public class IteratorEx {

	public static void main(String[] args) {
		
		List<String> list = Arrays.asList(new String[]{"홍길동", "김유신", 
				"이순신", "유관순"});
		System.out.println("for문 이용");
		for (int i=0; i<list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("외부 반복자 이용");
		Iterator<String> it = list.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		System.out.println("내부 반복자 이용");
		list.stream().forEach(s ->System.out.println(s));

	}

}

스트림 생성하기

package chapter16;

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

public class ArrayToStream {

	public static void main(String[] args) {
		
		// 문자열 배열객체 생성
		String[] arr = new String[]{"a", "b", "c", "d", "e", "f"};
		
		// 배열전체 Stream 객체로 변환
		Stream<String> stream1 = Arrays.stream(arr);
		stream1.forEach(s -> System.out.print(s+" "));
		System.out.println();
		
		// 인덱스 지정해서 변환 (2부터 5전까지)
		// 두번째 인덱스는 포함되지 않음
		Stream<String> stream2 = Arrays.stream(arr, 2, 5); 
		stream2.forEach(s -> System.out.print(s+" "));

	}

}

package chapter16;

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

public class CollectionToStream {

	public static void main(String[] args) {
		
		// 문자열 배열을 컬렉션프레임워크 List로 변환
		List<String> list = Arrays.asList("a", "b", "c", "d", "e");
		// List 객체를 stream()메서드를 이용해 Stream 객체로 생성
		Stream<String> stream = list.stream();
		// 내부반복자를 이용해 출력
		stream.forEach(s -> System.out.println(s));
				
	}
}

package chapter16;

import java.util.stream.Stream;

public class StreamByBuilder {

	public static void main(String[] args) {
		
		// generate() 메서드로 Stream 객체 생성
		// 리미트 10개 생성
		Stream<String> stream = Stream.generate(() -> "애국가").limit(10);
		// 내부 반복자로 출력
		stream.forEach(s -> System.out.println(s));

	}

}

package chapter16;

import java.util.stream.Stream;

public class StreamByIterator {

	public static void main(String[] args) {
		
		// generate() 메서드로 Stream 객체 생성
		// 리미트 10개 생성
		Stream<Integer> stream = Stream.iterate(1, n -> n + 1).limit(10);
		// 내부 반복자로 출력
		stream.forEach(s -> System.out.println(s));

	}

}

스트림의 종류

package chapter16;

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

public class IntStreamEx {

	public static void main(String[] args) {
		
		int[] arr = {1,2,3,4,5};
		
		System.out.println("Arrays.stream() IntStream 생성하기");
		IntStream intstream1 = Arrays.stream(arr);
		intstream1.forEach(s -> System.out.print(s+"\t"));
		System.out.println();
		
		System.out.println("IntStream.of() IntStream 생성하기");
		IntStream intstream2 = IntStream.of(arr);
		intstream2.forEach(s ->System.out.print(s+"\t"));
		System.out.println();
		
		// 두번째 매개변수 인덱스 포함안됨
		System.out.println("IntStream.range(1,6) IntStream 생성하기");
		IntStream intstream3 = IntStream.range(1,6);
		intstream3.forEach(s ->System.out.print(s+"\t"));
		System.out.println();
		
		System.out.println("IntStream.rangeClosed(1,5) IntStream 생성하기");
		IntStream intstream4 = IntStream.rangeClosed(1, 5);
		intstream4.forEach(s -> System.out.print(s+"\t"));

	}

}

package chapter16;

import java.util.Random;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class RandomToStream {

	public static void main(String[] args) {
		
		System.out.println("int 형 난수 스트림 : ");
		// ints(3) 3개
		IntStream isr = new Random().ints(3);
		isr.forEach(s -> System.out.println(s));
		
		// ints(갯수, 시작값, 끝값전까지)
		isr = new Random().ints(10,0,3);
		isr.forEach(s -> System.out.println(s));
		System.out.println();
		
		System.out.println("long 형 난수 스트림 : ");
		// longs(갯수, 시작값, 끝값전까지)
		LongStream lsr = new Random().longs(3,0,10);
		lsr.forEach(s -> System.out.println(s));
		System.out.println();
		
		System.out.println("double 형 난수 스트림 : ");
		// doubles(3) 3개
		DoubleStream dsr = new Random().doubles(3);
		dsr.forEach(s ->System.out.println(s));

	}

}

package chapter16;

import java.util.stream.IntStream;

public class StrToStream {

	public static void main(String[] args) {
		
		String str = "자바 세상을 만들자";
		
		// Stream 객체 생성
		IntStream isr = str.chars();
		
		// System.out.print()
		isr.forEach(s -> System.out.print((char)s));

	}

}

package chapter16;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
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 FileToStream {

	public static void main(String[] args) {
		
		try {
			// Paths.get() 메서드 사용
			Path path = Paths.get("src/chapter19/StrToStream.java");
			Stream<String> stream = Files.lines(path, Charset.defaultCharset());
			stream.forEach( s -> System.out.println(s));
			stream.close();
			System.out.println();
			
			//BufferedReader의 lines() 메소드 사용
			File file = path.toFile();
			FileReader fr = new FileReader(file);
			BufferedReader br = new BufferedReader(fr);
			br.lines().forEach( s -> System.out.println(s));
			stream.close();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

	}

}

package chapter16;

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

public class DirectoryToStream {

	public static void main(String[] args) {
		
		try {
			System.out.println("list() 메서드를 이용하여 스트림 생성하기");
			// src 디렉토리로 Path 객체 생성
			Path path = Paths.get("src");
			// src 경로의 모든 디렉토리와 파일 Stream 객체로 생성
			Stream<Path> sr1 = Files.list(path);
			sr1.forEach(p -> System.out.println(p.getFileName()));
			
			System.out.println("find() 메서드를 이용하여 스트림 생성하기");
			// src 디렉토리로 시작해서 10단계까지의 디렉토리 깊이까지 탐색
			Stream<Path> sr2 = Files.find(path, 10, 
					(p, basicFileAttributes) -> {
						File file = p.toFile();
						// 디렉토리가 아니고 파일이름에 Stream이 포함된 파일명 리턴
						return !file.isDirectory() && file.getName().contains("Stream");
					});
			sr2.forEach( p -> System.out.println(p.getFileName()));
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

	}

}

스트림 가공하기

package chapter16;

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

public class FilterStream {

	public static void main(String[] args) {
		
		// List 객체 생성
		List<String> list = Arrays.asList("홍길동", "김유신", "홍길동", 
										"이순신", "홍길동", "유관순");
		
		// distinct() 메서드로 중복 제거 후 내부 반복자로 출력
		System.out.println("distinct()");
		list.stream().distinct().forEach(n -> System.out.println(n));
		System.out.println();
		
		// "홍"으로 시작하는 문자열로 필터링 후 내부 반복자로 출력
		System.out.println("filter()");
		list.stream().filter(n -> n.startsWith("홍"))
					.forEach(n -> System.out.println(n));
		System.out.println();
		
		// 중복제거 후 "홍"으로 시작하는 문자열 내부 반복자로 출력
		System.out.println("distinct() + filter()");
		list.stream().distinct().filter(n -> n.startsWith("홍")).forEach(n -> System.out.println(n));

	}

}

package chapter16;

import java.util.Arrays;
import java.util.List;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;

public class StreamFlatMap {

	public static void main(String[] args) {
		
		// 문자열을 공백으로 분리해서 매핑
		List<String> list1 = Arrays.asList("동해물과", "백두산이", 
											"마르고 닳도록");
		list1.stream().flatMap(data -> Arrays.stream(data.split(" ")))
					.forEach(word -> System.out.println(word));
		System.out.println();
		
		// 문자열을 ,로 분리해서 double 자료형으로 변환해서 매핑
		List<String> list2 = Arrays.asList("1.1, 2.2, 3.3", "4.4, 5.5, 6.6");
		DoubleStream dsr = list2.stream().flatMapToDouble(data -> {
			String[] strArr = data.split(",");
			double[] dArr = new double[strArr.length];
			for(int i=0; i<dArr.length; i++) {
				dArr[i] = Double.parseDouble(strArr[i].trim());
			}
			return Arrays.stream(dArr);
		});
		dsr.forEach(n -> System.out.println(n));
		System.out.println();
		
		// 문자열을 ,로 분리해서 int 자료형으로 변환해서 매핑
		List<String> list3 = Arrays.asList("1, 2, 3", "4, 5, 6");
		IntStream isr = list3.stream().flatMapToInt(data -> {
			String[] strArr = data.split(",");
			int[] intArr = new int[strArr.length];
			for(int i=0; i<strArr.length; i++) {
				intArr[i] = Integer.parseInt(strArr[i].trim());
			}
			return Arrays.stream(intArr);
		});
		isr.forEach(n -> System.out.println(n));			

	}

}

package chapter16;

import java.util.Arrays;
import java.util.List;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;

public class StreamMap {

	public static void main(String[] args) {
		
		List<String> list = Arrays.asList("동해물과", "백두산이", 
											"마르고 닳도록");
		
		System.out.println("함수적 인터페이스 방식");
		list.stream().mapToInt(s -> s.length())
					.forEach(len -> System.out.println(len));
		System.out.println();
		
		System.out.println("메서드 참조 방식");
		list.stream().mapToInt(String::length)
					.forEach(len -> System.out.println(len));

	}

}

package chapter16;

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

public class StreamOrder {

	public static void main(String[] args) {
		
		List<String> list = Arrays.asList("홍길동", "김유신", "이순신", "유관순");
		
		System.out.println("기본 정렬");
		list.stream().sorted().forEach(System.out::println);
		System.out.println();
		
		System.out.println("역순 정렬");
		list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);

	}

}

package chapter16;

abstract class Shape implements Comparable<Shape>{
	
	// 필드
	int x, y;
	
	// 생성자
	Shape() {
		this(0, 0);
	}
	Shape(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	// 추상메서드
	abstract double area();
	abstract double length();
	
	// 일반 메서드
	public String getLocation() {
		return "x:" + x + ",y:" + y;
	}
	
	@Override
	public int compareTo(Shape s) {
		return (int)(this.area() - s.area()); 
	}
	
}

package chapter16;

public class Rectangle extends Shape {

	// 필드
	int w,h;
	
	// 생성자
	Rectangle() {
		this(1,1);
	}
	Rectangle(int w, int h) {
		this.w = w;
		this.h = h;
	}
	
	// 메서드 재정의(오버라이딩)
	@Override
	double area() {
		return (w * h);
	}
	
	@Override
	double length() {
		return (w + h) * 2;
	}
	
	@Override
	public String toString() {
		return "넓이 : "+this.area();
	}
	
}

package chapter16;

public class Circle extends Shape {

	// 필드
	double r;
	
	// 생성자
	Circle() {
		this(1);
	}
	Circle(double r) {
		this.r = r;
	}
	
	// 메서드 재정의(오버라이딩)
	@Override
	double area() {
		return (r * r) * Math.PI;
	}
	
	@Override
	double length() {
		return (r * 2) * Math.PI;
	}
	
	@Override
	public String toString() {
		return "넓이 : "+this.area();
	}
	
}

package chapter16;

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

public class StreamOrder2 {

	public static void main(String[] args) {
		
		Shape s1 = new Rectangle(10,3);
		Shape s2 = new Circle(10);
		Shape s3 = new Rectangle(20,2);
		Shape s4 = new Circle(11);
		
		List<Shape> list = Arrays.asList(s1, s2, s3, s4);
		
		System.out.println("오름차순 정렬");
		list.stream().sorted().forEach(System.out::println);
		
		System.out.println("내림차순 정렬 1");
		list.stream().sorted((a,b) -> b.compareTo(a) - a.compareTo(b) ).forEach(System.out:: println);
		
		System.out.println("내림차순 정렬 2");
		list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);
				
	}
}

package chapter16;

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

public class StreamOrder3 {

	public static void main(String[] args) {
		
		Shape s1 = new Rectangle(10,3);
		Shape s2 = new Circle(10);
		Shape s3 = new Rectangle(20,2);
		Shape s4 = new Circle(11);
		
		List<Shape> list = Arrays.asList(s1, s2, s3, s4);
		
		System.out.println("정렬하지 않고 출력");
		list.stream().forEach(System.out::println);
		
		System.out.println("둘레(length()) 순으로 정렬");
		System.out.println("함수적 인터페이스로 구현");
		list.stream().sorted(new Comparator<Shape>() {
			@Override
			public int compare(Shape s1, Shape s2) {
				return (int)(s1.length() - s2.length());
			}
		}).forEach(System.out::println);
		
		System.out.println("람다표현식을 이용하여 둘레순으로 정렬");
		list.stream().sorted((a,b) -> (int)(a.length() - a.length()) ).forEach(System.out:: println);
		
				
	}
}

package chapter16;

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

public class StreamPeek {

	public static void main(String[] args) {
		
		Shape s1 = new Rectangle(10,3);
		Shape s2 = new Circle(10);
		Shape s3 = new Rectangle(20,2);
		Shape s4 = new Circle(11);
		
		List<Shape> list = Arrays.asList(s1, s2, s3, s4);
		
		// 모든 요소들이 Shape의 인스턴스(객체)인지 조건 비교
		boolean result = list.stream().allMatch(a -> (a instanceof Shape));
		System.out.println("모든 요소는 Shape의 객체이다. -> " + result);
		
		// 요소들 중 하나이상이 Rectangle 객체인지 조건 비교
		boolean result2 = list.stream().anyMatch(a -> (a instanceof Rectangle));
		System.out.println("요소 중 Rectangle의 객체가 존재한다. -> " + result2);
		
		// 모든 요소가 Circle의 객체인지 조건에 해당하지 않는지 비교
		boolean result3 = list.stream().noneMatch(a -> (a instanceof Circle));
		System.out.println("모든 요소 중 Circle의 객체가 존재하지 않는다. -> " + result3);
				
	}
}

package chapter16;

import java.util.Arrays;
import java.util.OptionalDouble;
import java.util.OptionalInt;

public class StreamOptional {

	public static void main(String[] args) {
		
		int[] arr = new int[100];
		for(int i=0;i<100;i++) {
			arr[i] = i+1;
		}

		// 리턴값 long
		long count = Arrays.stream(arr).count();
		System.out.println("요소들의 갯수 : " + count);
		
		// 리턴값 int
		int sum = Arrays.stream(arr).sum();
		System.out.println("요소들의 합 : " + sum);
		
		OptionalInt first = Arrays.stream(arr).findFirst();
		System.out.println("요소들 중 첫번째 값 : " + first.getAsInt());
		
		OptionalInt max = Arrays.stream(arr).max();
		System.out.println("요소들 중 최대 값 : " + max.getAsInt());
		
		OptionalInt min = Arrays.stream(arr).min();
		System.out.println("요소들 중 최소 값 : " + min.getAsInt());
		
		OptionalDouble avg = Arrays.stream(arr).average();
		System.out.println("요소들의 평균 : " + avg.getAsDouble());
		
		

	}

}

package chapter16;

import java.util.ArrayList;
import java.util.List;
import java.util.OptionalDouble;
import java.util.OptionalInt;

public class StreamOptionalNoElem {

	public static void main(String[] args) {
		
		// 요소가 없는 빈 ArrayList 객체 생성
		List<Integer> list = new ArrayList<Integer>();
		
		long count =list.stream().count();
		System.out.println("요소들의 갯수 : " + count);
		
		int sum =list.stream().mapToInt(Integer::intValue).sum();
		System.out.println("요소들의 합 : " + sum);
		
		OptionalDouble avg = list.stream().mapToInt(Integer::intValue).average();
		System.out.println("요소들의 평균 : " + avg.getAsDouble());
		
		OptionalInt max =list.stream().mapToInt(Integer::intValue).max();
		System.out.println("요소들 중 최대 값 : " + max.getAsInt());
		
		OptionalInt min =list.stream().mapToInt(Integer::intValue).min();
		System.out.println("요소들 중 최소 값 : " + min.getAsInt());
		
		OptionalInt first =list.stream().mapToInt(Integer::intValue).findFirst();
		System.out.println(" 요소들 중 첫번째 값 : " + first.getAsInt());
		
		

	}

}

package chapter16;

import java.util.ArrayList;
import java.util.List;
import java.util.OptionalDouble;
import java.util.OptionalInt;

public class StreamOptionalNoElem2 {

	public static void main(String[] args) {
		
		// 요소가 없는 빈 ArrayList 객체 생성
		List<Integer> list = new ArrayList<Integer>();
		
		long count =list.stream().count();
		System.out.println("요소들의 갯수 : " + count);
		
		int sum =list.stream().mapToInt(Integer::intValue).sum();
		System.out.println("요소들의 합 : " + sum);
		
		OptionalDouble avg = list.stream().mapToInt(Integer::intValue).average();
		// 요소가 존재하는 경우에만 평균 출력
		if(avg.isPresent()) {
			System.out.println("요소들의 평균 : " + avg.getAsDouble());
		}
		
		// 요소값이 없는 경우 기본값 설정
		int max =list.stream().mapToInt(Integer::intValue).max().orElse(0);
		System.out.println("요소들 중 최대 값 : " + max);
		
		// 요소값이 없는 경우 기본값 설정
		int min =list.stream().mapToInt(Integer::intValue).min().orElse(-1);
		System.out.println("요소들 중 최소 값 : " + min);
		
		// 요소가 존재하면 실행
		list.stream().mapToInt(Integer::intValue)
				            .findFirst().ifPresent(a -> System.out.println("요소 중 첫번째 값: "+a));
		
		

	}

}

package chapter16;

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

public class StreamReduce {

	public static void main(String[] args) {
		
		Shape s1 = new Rectangle(10,3);
		Shape s2 = new Circle(10);
		Shape s3 = new Rectangle(20,2);
		Shape s4 = new Circle(11);
		
		List<Shape> list = Arrays.asList(s1, s2, s3, s4);
		
		double areaSum = list.stream().mapToDouble(Shape::area).sum();
		System.out.println("sum()를 이용한 면적 합계 :" + areaSum);
		areaSum = list.stream().mapToDouble(Shape::area).reduce((a, b) -> a+b).getAsDouble();
		System.out.println("reduce(Operator) 를 이용한 면적 합계 :" + areaSum);
		
		areaSum = list.stream().mapToDouble(Shape::area)
				.reduce(0,(a,b) -> a+b);
		System.out.println("reduce(0,Operator) 를 이용한 면적 합계 :" + areaSum);
				
	}
}

package chapter16;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class StreamCollect {

	public static void main(String[] args) {
		
		Shape s1 = new Rectangle(10,3);
		Shape s2 = new Circle(10);
		Shape s3 = new Rectangle(20,2);
		Shape s4 = new Circle(11);
		
		List<Shape> list = Arrays.asList(s1, s2, s3, s4);
		
		// 요소가 Rectangle 객체인 경우 collect 메서드로 List로 변환 
		List<Shape> rectList = list.stream().filter(s -> s instanceof Rectangle).collect(Collectors.toList());
		rectList.stream().forEach(f -> System.out.println(f));
		System.out.println();
		
		// 요소가 Rectangle 객체인 경우 collect 메서드로 Set으로 변환
		Set<Shape> rectSet = list. stream().filter(s -> s instanceof Rectangle).collect(Collectors.toSet());
		rectSet.stream().forEach(f -> System.out.println(f));
	}
}

package chapter16;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class StreamGroupingBy {

	public static void main(String[] args) {
		
		Shape s1 = new Rectangle(10,3);
		Shape s2 = new Circle(10);
		Shape s3 = new Rectangle(20,2);
		Shape s4 = new Circle(11);
		
		List<Shape> list = Arrays.asList(s1, s2, s3, s4);
		
		try {
			// 객체 타입으로 그룹핑 (Rectangle, Circle)
			Map<Object,List<Shape>> map = list.stream().collect(Collectors.groupingBy(f -> f.getClass()));
			
			System.out.println("사각형 출력");
			map.get(Class.forName("chapter19.Rectangle")).stream().forEach(f -> System.out.println(f));
			
			System.out.println("원 출력");
			map.get(Class.forName("chapter19.Circle")).stream().forEach(f -> System.out.println(f));
			
		} catch (ClassNotFoundException e) {
			System.out.println(e.getMessage());
		}
	}
}

스트림 병렬처리

package chapter16;

import java.util.ArrayList;
import java.util.List;

public class StreamParallel {

	public static void main(String[] args) {
		
		List<Integer> list = new ArrayList<Integer>();
		for(int i=0;i<100;i++) {
			list.add(i);
		}
		long start = System.nanoTime();
		// stream() 순차적 스트림 처리
		list.stream().forEach(a -> {
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});
		
		long end = System.nanoTime();
		System.out.println("순차 스트림 처리 시간 : " + (end - start) + "nano sec");
		
		
		start = System.nanoTime();
		// parallelStream() 병렬 스트림 처리
		list.parallelStream(). forEach(a -> {
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});
		end = System.nanoTime();
		System.out.println("병렬 스트림 처리 시간 : " + (end - start) + "nano sec");

	}

}

스트림 연결하기

package chapter16;

import java.util.stream.Stream;

public class StreamConcat {

	public static void main(String[] args) {

		// 문자열 스트림 객체
		Stream<String> stream1 = Stream.of("홍길동", "김유신", "이순신", "유관순");
		// 정수 스트림 객체
		Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6,7,8,9,10);
		
		// concat() 메서드로 두 스트림 객체 
		Stream<Object> concat = Stream.concat(stream1, stream2);
		concat.forEach(a -> System.out.print(a + ","));

	}

}