자바

JAVA STEP 48. Stream

IT의 큰손 2023. 3. 2. 19:12
728x90

★ Stream

  • Java 8
  • 배열(컬렉션)의 탐색(조작)
  • 파일 입출력
  • 디렉토리 탐색
  • 빈번하게 익명 객체를 사용 > 람다식 사용 + 표준 API 함수 인터페이스 사용

1. 파이프

  • 스트림 객체 메소드
  • 1-1. 중간 파이프
    • 반환값 > 스트림 반환
  • 1-2. 최종 파이프
    • 반환값 > 스트림 아닌 다른 자료형을 반환 or void(반환값 x)

2. 필터링

  • filter() 메소드
  • 중간 파이프
  • 앞의 스트림의 값들을 받아서 > 검사 > 조건을 만족하는 요소만 남겨 > 스트림 생성

3. 중복제거

  • distinct() 메소드
  • 중간파이프
  • 앞의 스트림의 값들을 받아서 > 중복값을 제거한 새로운 스트림 생성
  • 유일한 값들로만 되어있는 스트림을 생성 
  • Set 성질과 유사 

4. 변환(매핑)

  • map(), mapXXX()
  • 중간 파이프
  • 앞의 스트림의 값들을 받아서 > 다른 값으로 변환한 새로운 스트림 생성 

5. 정렬

  • sorted()
  • 중간 파이프
  • 앞의 스트림의 값들을 받아서 > 정렬된 상태의 새로운 스트림 생성
  • 이전 컬렉션의 sort(Comparator)와 동일

6. 탐색

  • forEach() 메소드
  • 최종 파이프
  • 앞의 스트림의 값들을 받아서 소비

7. 매칭

  • allMatch(), anyMatch(), noneMatch()
  • 최종 파이프
  • a. boolean allMatch(Predicate) : 모든 요소가 만족하는지? (&&)
  • b. boolean anyMatch(Predicate) : 일부 요소가 만족하는지? (||)
  • c. boolean noneMathch(Predicate) : 모든 요소가 불만족하는지?

8. 집계(Reduce)

  • count(), max(), min(), sum(), avg()
  • 최종 파이프
  • 앞의 스트림의 값들을 받아서 > 통계값

 

■ 배열을 읽을 때 다양한 방법 예제

  • 소스코드
  •  
private static void m2() {
		
		//배열(컬렉션) 탐색
		List<Integer> list = Data.getIntList(10);
		
		//1. for문(while문)
		for (int i=0; i<list.size(); i++) {
			System.out.printf("%5d", list.get(i));
		}
		System.out.println();
		
		//2. 향상된 for문
		for (int n : list) {
			System.out.printf("%5d", n);
		}
		System.out.println();
		
		//3. Iterator
		Iterator<Integer> iter = list.iterator();
		
		while(iter.hasNext()) {
			System.out.printf("%5d", iter.next());
		}
		System.out.println();
		
		//4. stream
		Stream<Integer> stream = list.stream();
		
		Consumer<Integer> c1 = num -> System.out.printf("%5d",num);;
		//c1.accept(10);
		
		//*** forEach 메소드의 행동
		//1. stream > 배열(컬렉션)으로부터 데이터 집합을 공급받는다.
		//2. forEach > 공급받은 데이터를 하나씩 처리(하나씩 꺼내서 출력하는것 밖에 못함)
		//3. Consumer > forEach가 하나씩 꺼내온 데이터를 스스로 처리(x) > 컨슈머에게 전달+처리
		stream.forEach(c1); //배열 탐색 > c1.accept(n) x 10회 호출
		
		System.out.println();
		
		List<Double> list2 = Data.getDoubleList(10);
		
		Stream<Double> stream2 = list2.stream();
		
		Consumer<Double> c2 = num -> System.out.printf("%.1f\n",num);
		
		stream2.forEach(c2);
		
		System.out.println();
		System.out.println();
		System.out.println();
		
		//메소드 체인
		//- 메소드의 반환값에 바로 또 다른 메소드를 연결시킨 모습
		//- 함수형 프로그래밍 방식
		Data.getDoubleList(10).stream().forEach(num->System.out.printf("%.1f\n",num));
		System.out.println();
		System.out.println();
		Data.getStringList(10).stream().forEach(txt -> System.out.println(txt.length()));
		Data.getStringList(10).stream().forEach(txt -> System.out.println(txt));
		System.out.println();
		System.out.println();
		Data.getUserList().stream().forEach(user -> {
			System.out.println("이름 : " + user.getName());
			System.out.println("나이 : " + user.getAge());
			System.out.println();
		});
		
	}

 

■ 스트림을 얻어오는 방법

  • 1. 컬렉션으로부터
  • 2. 배열로부터
  • 3. 숫자범위로부터
  • 4. 파일로부터
  • 5. 디렉토리로부터
  • 소스코드
  •  
private static void m3() {
		
		//1. 컬렉션으로부터
		ArrayList<Integer> nums1 = new ArrayList<Integer>();
		nums1.add(100);
		nums1.add(200);
		nums1.add(300);
		
		nums1.stream().forEach(num -> System.out.println(num));
		System.out.println();
		
		LinkedList<Integer> nums2 = new LinkedList<Integer>();
		nums2.add(1000);
		nums2.add(2000);
		nums2.add(3000);
		
		nums2.stream().forEach(num -> System.out.println(num));
		System.out.println();
		
		HashSet<Integer> nums3 = new HashSet<Integer>();
		nums3.add(10000);
		nums3.add(20000);
		nums3.add(30000);
		
		nums3.stream().forEach(num -> System.out.println(num));
		System.out.println();
		
		//HashMap<String,Integer> map;
		//map.stream() >> 불가능
		//map.entrySet().stream()
		
		//2. 배열로 부터
		int[] nums4 = { 111, 222, 333, 444, 555};
		Arrays.stream(nums4).forEach(num -> System.out.println(num));
		System.out.println();
		
		//3. 숫자 범위로 부터
		//- Stream<T> : 범용 스트림
		//- IntStream : 전용 스트림
		IntStream.range(1, 11).forEach(num -> System.out.println(num));
		System.out.println();
		
		//4. 파일로 부터 
		//- 파일 읽기
		try {
			
			//File file = new File()
			Path path = Paths.get("/Users/kimdaehwan/Desktop/class/code/java/JavaTset/dat/user.txt");
			
			Files.lines(path).forEach(line -> System.out.println(line));
			System.out.println();
			
		//5. 디렉토리로부터
		//- 목록보기 > dir.listFiles()
		
			Path dir = Paths.get("/Users/kimdaehwan/Desktop/Quest");
			
			Files.list(dir).forEach(p -> {
				System.out.println(p.getFileName());
				System.out.println(p.toFile().length());
			});
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

 

■ 요구사항 : 짝수만 화면에 출력

  • 소스코드
  •  
private static void m4() {
		
		List<Integer> list = Data.getIntList(20);
		System.out.println(list);
		
		//요구사항] 짝수만 화면에 출력하시오.
		
		//1. for
		for(int i=0; i<list.size(); i++) {
			if(list.get(i) %2 ==0) {
				System.out.printf("%4d", list.get(i));
			}
		}
		System.out.println();
		
		//2. for
		for(int n: list) {
			if(n%2 ==0 ) {
				System.out.printf("%4d", n);
			}
		}
		System.out.println();
		
		//3. stream
		list.stream().forEach(num -> {
			
			if(num%2 == 0) {
				System.out.printf("%4d", num);
			}
			
		});
		System.out.println();
		
		//4. stream
		//- filter
		list.stream().filter(num -> {
			if(num%2 == 0) {
				return true;
			} else {
				return false;
			}
		}).forEach(num -> System.out.printf("%4d",num));
		System.out.println();
		
		list.stream().filter(num -> num %2==0).forEach(num -> System.out.printf("%4d", num));
		System.out.println();
		
		list.stream()
			.filter(num -> num%2==0 && num>=50)
			.forEach(num -> System.out.printf("%4d", num));
		System.out.println();
		
		list.stream()
			.filter(num -> num%2==0)
			.filter(num-> num >=50)
			.forEach(num -> System.out.printf("%4d", num));
		System.out.println();
		System.out.println();
		
		Data.getStringList().stream()
							.filter(word -> word.length()>=5)
							.filter(word -> word.startsWith("애플"))
							.forEach(word -> System.out.println(word));
		System.out.println();
		
		Data.getUserList().stream()
						  .filter(user -> user.getGender() == 1)
						  .filter(user -> user.getHeight() >= 180)
						  .filter(user -> user.getWeight() >= 80)
						  .forEach(user -> System.out.println(user));
		System.out.println();
		
	}

 

■ 요구사항 : 집합에서 중복값 > 유일한 값들을 출력하시오.

  • 소스코드
  •  
private static void m5() {
		List<Integer> list = Data.getIntList();
		System.out.println(list.size());
		
		//요구사항] 집합에서 중복값 > 유일한 값들을 출력하시오.
		//System.out.println(list);
		
		//Case 1.
		Set<Integer> set = new HashSet<Integer>();
		
		for (int n : list) { //100개
			set.add(n); //중복값 배제
		}
		
		System.out.println(set.size());
		System.out.println(set);
		
		//Case 2.
		//- ArrayList > (변환) > HashSet
		Set<Integer> set2 = new HashSet<Integer>(list);
		System.out.println(set2);
		
		//Case 3.
		list.stream()
			.distinct() //중복제거
			.forEach(num -> System.out.printf("%4d",num));
		System.out.println();
		
		Data.getStringList().stream()
							.filter(word -> word.length() > 5)
							.distinct()
							.forEach(word -> System.out.println(word));
		System.out.println();
		
		List<Student> slist = new ArrayList<Student>();
		
		slist.add(new Student("가가가", 20, "남자" ));
		slist.add(new Student("나나나", 20, "남자" ));
		slist.add(new Student("다다다", 20, "남자" ));
		slist.add(new Student("홍길동", 20, "남자" ));
		slist.add(new Student("홍길동", 20, "남자" ));
		
		slist.stream()
			.distinct()
			.forEach(s -> System.out.println(s));
		System.out.println();
		
	}

 

■ map 사용 예제

  •  소스코드
  •  
private static void m6() {
		
		//map
		List<String> list = Data.getStringList(10);
		System.out.println(list);
		System.out.println();
		
		list.stream()
			.forEach(word -> System.out.printf("%3d" , word.length()));
		System.out.println();
		
		list.stream()
			.map(word -> word.length())
			.forEach(num -> System.out.printf("%3d", num));
		
		list.stream()
			.map(word -> word.substring(0,2))
			.forEach(word -> System.out.printf("%4s", word));
		System.out.println();
		
		String[] names = {"홍길동", "유재석", "박명수", "박나래", "장도연" };
		
		Arrays.stream(names)
			.map(name -> name.substring(1))
			.forEach(name -> System.out.printf("%4s",name));
		System.out.println();
		
		for(int i=0; i<names.length; i++) {
			
			String firstName = names[i].substring(1); //이름
			String lastName = names[i].substring(0,1); //성
			
			Name name = new Name();
			name.setFirstName(firstName);
			name.setLastName(lastName);
			
			System.out.println(name.getFirstName()+ "," + name.getLastName());
		}
			System.out.println();
			
			Arrays.stream(names)
				.map(name -> {
					
					String firstName = name.substring(1); //이름
					String lastName = name.substring(0,1); //성
					
					Name n = new Name();
					n.setFirstName(firstName);
					n.setLastName(lastName);
					
					return n;
				}).forEach(name -> {
					System.out.println(name.getFirstName()+ "," + name.getLastName());
				});
			
			Data.getIntList(5)
				.stream()
				.map(num -> 1)
				.forEach(n -> System.out.println(n));
			System.out.println();
			
			Data.getUserList().stream()
							  .forEach(user -> System.out.println(user.getName()));
			System.out.println();
			
			Data.getUserList().stream()
							  .map(user -> user.getName())
							  .forEach(name -> System.out.println(name));
			System.out.println();
	}

 

■ 정렬 사용 예제

  • 소스코드
  •  
private static void m7() {
		
		Data.getIntList(10).stream().forEach(num -> System.out.println(num));
		System.out.println();
		
		Data.getIntList(10).stream()
						   .sorted()
						   .forEach(num -> System.out.println(num));
		System.out.println();
		
		Data.getIntList(10).stream()
		   				   .sorted((a,b) -> b-a)
		   				   .forEach(num -> System.out.println(num));
		System.out.println();
		
		Data.getItemList().stream()
						  .sorted((a,b) -> a.getName().compareTo(b.getName()))
						  // 불가능 : .sorted((a,b) -> a.getSize()-a.getSize()) : 2차 정렬X
						  .forEach(item -> System.out.println(item));
		System.out.println();
		
		List<Integer> list = Data.getIntList(10);
		
		System.out.println(list);
		
		Collections.sort(list);				  //오름차순
		Collections.sort(list, (a,b) -> b-a); //내림차순
		
		list.sort((a,b) -> a - b);			  //오름차순
		list.sort((a,b) -> b - a);			  //내림차순
		
		list.sort(Comparator.naturalOrder()); //오름차순
		list.sort(Comparator.reverseOrder()); //내림차순
		
		Data.getIntList().stream()
						 .distinct()
						 .filter(n-> n%2 ==0)
						 .sorted()
						 .forEach(n -> System.out.println(n));
		
		
	}

 

■ 매칭 사용 예제

  • 소스코드
  •  
private static void m8() {
		
		int[] nums = { 2, 4, 6, 8, 10};
		
		//요구사항] 배열안에 짝수만 있는지?
		
		boolean result = true;
		
		for(int n: nums) {
			if(n%2 ==1) {
				result = false;
				break;
			}
		}
		
		if (result) {
			System.out.println("짝수만 발견!!");
		}else {
			System.out.println("홀수 발견!!");
		}
		
		result = Arrays.stream(nums).allMatch(n -> n%2 == 0);
		
		if (result) {
			System.out.println("짝수만 발견!!");
		}else {
			System.out.println("홀수 발견!!");
		}
		
		//요구사항] nums안에 홀수가 1개 이상 존재하는지?
		result = Arrays.stream(nums).anyMatch(n -> n%2 ==1);
		System.out.println(result);
		
		//요구사항] nums안에 모두 홀수가 아닌가?
		result = Arrays.stream(nums).noneMatch(n -> n%2 ==1);
		System.out.println(result);
		
		System.out.println(Data.getUserList());
		System.out.println();
		
		result = Data.getUserList().stream().anyMatch(user -> user.getHeight() >= 180);
		System.out.println(result);
		
		result = Data.getUserList().stream().allMatch(user -> user.getGender() ==1);
		System.out.println(result);
		
		result = Data.getUserList().stream()
						.filter(user -> user.getHeight() >= 180)
						.allMatch(user -> user.getGender() ==1);
		System.out.println(result);
		
		result = Data.getUserList().stream()
						.noneMatch(user -> user.getWeight() < 60);
		System.out.println(result);
		
		
	}
728x90