스트림은 코드를 직관적으로 이해 작성하고 다양한 유형의 데이터를 일관된 방식으로 다룰 수 있게 하기 위해 만들어진 문법이다
스트림은 생성, 중간 연산, 최종 연산으로 구성할 수 있다
스트림은 작업을 내부 반복으로 처리한다
Iterator는 대표적인 외부 반복 처리스트림은 데이터 소스를 변경하지 않고(read-only), 일회용이다(onetime-only)
public class StreamPractice {
	public static void main(String[] args) {
    	BaseStream; // 스트림에서 사용되는 기본 추상메서드들이 들어있음
        	Stream; // 객체 요소를 처리하는 스트림
            IntStream; // Int형 기본 타입 요소를 처리하는 스트림
            LongStream; 
            DoubleStream; 
    	
        new int[] { 1, 2, 3, 4, 5 }
        Stream<Integer>; // Integer 타입으로 입력됨
        IntStream; // 기본타입의 요소가 바로 입력됨
        sum(),  average(), max(), min(), count()
    }
}
public class StreamPractice {
	public static void main(String[] args) {
		// Stream.of & Arrays.stream(arr)
        
        String[] arr = new String[] {
        	"본인임", "언민이", "현이형", "땅미쿤", "곽삼촌", "쭈쀼쨩" 
        }
        System.out.println("배열 스트림 생성 : Arrays.stream()");
        Stream<String> arrStream1 = Arrays.stream(arr);
        
        arrStream1.forEach(name -> System.out.print(name + " "));
        System.out.println("");
        
        System.out.println("배열 스트림 생성 : Stream.of()");
        Stream<String> arrStream2 = Stream.of(arr);
        
        arrStream2.forEach(name -> System.out.print(name + " "));
        System.out.println("\n");
        
        int[] arr1 = new int[] {
        	1, 2, 3, 4, 5, 6, 7, 8, 9, 10
        };
        
        System.out.println("기본형 스트림 생성")
        Stream<String> intStream1 = Arrays.stream(arr1);
        Stream<String> intStream2 = Stream.of(arr1);
        
        intStream1.forEach(System.out::print);
        System.out.println();
        intStream2.forEach(System.out::print);
        System.out.println("\n");
        
        System.out.println("컬렉션 스트림 생성 : 컬렉션.Stream()");
        ArrayList<String> arrayList = new ArrayList<>(Arrays.asList(arr));
        
        Stream<String> arrayListStream = arrayList.stream();
        arrayListStream.forEach(name -> System.out.print(name + " "));
        System.out.println();
        
        System.out.println("지정한 범위 내의 숫자 스트림 생성 : IntStream.range()");
        IntStream rangeInts = IntStream.rangeClosed(0, 10);
        rangeInts.forEach(num -> System.out.print(num + " ");
        System.out.println("\n");
    }
}
forEach로 각각의 요소가 name에 할당됨 -> 뒤의 코드가 실행됨public class StreamPractice {
	public static void main(String[] args) {
        IntStream rangeInts = IntStream.rangeClosed(0, 10);
        
        // 스트림 자르기
        // skip(n) -> 스트림의 처음 n개의 요소를 건너뜀
        // limit(n) -> 스트림의 요소를 최대 n개로 제한
        
        rangeInts
        		.skip(2)
                .limit(6)
                .forEach(num -> System.out.print(num + " "));
    }
}
// 출력값
// 3, 4, 5, 6, 7, 8
limit()의 숫자값은 '최대' 갯수 제한임을 유의public class StreamPractice {
	public static void main(String[] args) {
		String[] arr = new String[] {
        	"본인임", "언민이", "현이형", "땅미쿤", "곽삼촌", "쭈쀼쨩",
            "본인임", "언민이", "현이형", "땅미쿤", "곽삼촌", "쭈쀼쨩" 
        }
        
        Stream<String> arrStream1 = Arrays.stream(arr);
        
        strStream
        		.distinct() // 중복값 제거
                .filter(name -> name.contains("현") 
                .forEach(name -> System.out.print(name + " "));
    }
}
// 출력값
// 현이형
filter()의 값으로는 람다식이 들어가야 한다각 요소마다 일정한 처리를 통해 다른 요소로 변환시키는 것
public class StreamPractice {
	public static void main(String[] args) {
		String[] arr = new String[] {
        	"본인임", "언민이", "현이형", "땅미쿤", "곽삼촌", "쭈쀼쨩",
            "본인임", "언민이", "현이형", "땅미쿤", "곽삼촌", "쭈쀼쨩" 
        }
        
        Stream<String> arrStream1 = Arrays.stream(arr);
        
        strStream
        		.distinct() // 중복값 제거
                .filter(name -> name.contains("현") 
                .map(name -> name + "짱")
                .forEach(name -> System.out.print(name + " "));
    }
}
//출력값
//현이형짱
		Set<Map.Entry<String, Integer>> entrySet = hashMap.entrySet();
		entrySet.stream()
				.mapToInt(entry->entrygetValue())
				.forEach(wash -> System.out.print(wash + " "));
String[][] strArr = new String[][] {};
String<String[]> outerStream = Arrays.stream(strArr);
outerStream
		.flatMap(innerArr -> Arrays.stream(innerArr))
        .forEach(name -> System.out.print(name + " "));
outerStream의 요소인 배열의 주소값이 직접 출력된다String[][] strArr = new String[][] {};
String<String[]> outerStream = Arrays.stream(strArr);
outerStream
		.flatMap(innterArr -> Arrays.stream(innerArr))
        .sorted((a, b) -> a.length() - b.length())
        .forEach(name -> System.out.print(name + " "));     
sorted() 안에 람다식을 입력하여 원하는 정렬로 만들 수 있다