백엔드/Java

Java 스트림(Stream)

짱뚱짱 2024. 10. 30. 09:00

📢 Stream(스트림)

 - 실제 입력(출력)되는 데이터의 흐름.
 - 파이프라인으로 데이터가 흘러가는 흐름의 개념
 - 스트림은 자료에 스트림을 생성하여 연산(복사본)
 - 스트림 연산은 연산을 다 수행하면 소모됨.(1회성)
 - 기존 자료를 복사하여 스트림을 구성하기 때문에 기존 자료의 변경을 유발하지 않음.

📢 Stream(스트림)용 연산이 별도 존재

중간연산 최종연산
메서드를 이어서 사용할 수 있음.

distinct() : 중복제거

filter() : 조건에 맞는 자료만 다음 스트림으로 이동

limit() : 스트림의 일부를 잘라냄

skip() : 스트림의 일부를 건너뜀

sorted() : 정렬 ...

map() : 새로운 형태로 변경 

mapToInt() / mapToLong() 

스트림의 최종 결과 연산 (마지막에서만 가능)


forEach(), count(), sum(), allMatch() : 스트림요소가 전부 일치하는지..


anyMatch() : 하나라도 일치하는지...


toArray() : 배열로 변환


collect() : 스트림 수집

 

📢 실습(1)

package day09;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.stream.Stream;

public class Stream01 {

	public static void main(String[] args) {
		int[] arr = {1,2,3,4,5,6,7,8,9};
		//일반적인 합계
		int sum=0;
		for(int i:arr) {
			sum+=i;
		}
		System.out.println(sum);
		System.out.println("스트림을 이용한 합계 sum()");
		
		int total = Arrays.stream(arr).sum();
		System.out.println(total);
		System.out.println("--스트림 count()--");
		//count()연산은 return => Long
		long cnt = Arrays.stream(arr).count();
		System.out.println(cnt);
		
		//Optional: nullPointException같은 Exception을 처리할 수 있게 도와줌.
		System.out.println("--스트림 average()--");
		OptionalDouble avg = Arrays.stream(arr).average();
		System.out.println(avg);
		
		// filter() : 조건
		// 배열의 값 중 5 이상만 출력
		Arrays.stream(arr).filter(n-> n>=5).forEach(m->{
			System.out.print(m+" ");
		});
		System.out.println();
		// 5이상의 합계 출력
		int sum2 = Arrays
				.stream(arr)
				.filter(n-> n>=5)
				.sum();
		System.out.println(sum2);
		
		int[] score = {78, 89, 86, 58, 74, 51, 63, 89, 90};
		//Stream을 이용하여 합계, 평균, 최대값
		//Stream을 이용하여 70점 이상의 인원수 
		int scoreSum = Arrays.stream(score).sum();
		OptionalDouble scoreAvg = Arrays.stream(score).average();
		OptionalInt scoreMax = Arrays.stream(score).max();
		long scorePassCount = Arrays.stream(score).filter(n-> n>=70).count();
		
		System.out.println("합계:"+scoreSum + " / 평균:"+scoreAvg+" / 최대값:"+scoreMax+" / 70점 이상:"+scorePassCount+"명");
		
		ArrayList<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(5);
		list.add(3);
		list.add(1);
		list.add(2);
		list.add(4);
		list.add(3);
		list.add(1);
		list.add(5);
		list.add(1);
		list.add(4);
		
		System.out.println("--list stream 구성--");
		list.stream().forEach(n->System.out.print(n+" "));
		System.out.println();
		
		System.out.println("--distinct() 중복제거--");
		list.stream()
		.distinct()
		.forEach(n->System.out.print(n+" "));
		
		System.out.println();
		System.out.println("--sorted() 정렬--");
		list.stream()
		.sorted()
		.distinct()
		.forEach(n->System.out.print(n+" "));
		
		System.out.println();
		//합계 > intStream 에게만 존재
//		int s = list.stream().sum();
		// map: 스트림 변환에 사용하는 중간연산
		//mapToInt : map 값을 int로 변환
		int s = list.stream()
				.mapToInt(n->n.intValue())
				.sum();
		
		System.out.println(s);
		
		// 스트림 객체 생성
		System.out.println("--Stream 객체 생성--");
		Stream<Integer> s1 = Stream.of(10,20,30,40,50,60);
		
		int s2 = s1.mapToInt(n->n.intValue()).sum();
		System.out.println(s2);
		
		//이미 소모된 스트림은 다시 사용할 수 없음.
//		OptionalDouble avg3 = s1.mapToInt(n->n.intValue()).average();
//		System.out.println(avg3);
		
	}

}

 

 

결과

45
스트림을 이용한 합계 sum()
45
--스트림 count()--
9
--스트림 average()--
OptionalDouble[5.0]
5 6 7 8 9 
35
합계:678 / 평균:OptionalDouble[75.33333333333333] / 최대값:OptionalInt[90] / 70점 이상:6명
--list stream 구성--
1 5 3 1 2 4 3 1 5 1 4 
--distinct() 중복제거--
1 5 3 2 4 
--sorted() 정렬--
1 2 3 4 5 
30
--Stream 객체 생성--
210

 

 

📢 실습(2)

package day09;

import java.util.Arrays;

public class Stream02 {

	public static void main(String[] args) {
		/* 배열에서 짝수만 출력(정렬) 중복되는 값이 있다면 제거
		 *  */
		
		int[] arr = {1,8,5,4,9,6,3,1,2,4,7,8,5,7};
		Arrays.stream(arr)
		.filter(n-> n%2 == 0)
		.distinct()
		.sorted()
		.forEach(System.out::println);
		
		System.out.println("-------------------");
		//배열로 리턴
		int[] result = Arrays.stream(arr)
				.filter(n-> n%2 == 1)
				.distinct()
				.sorted()
				.toArray();
		for(int tmp:result) {
			System.out.println(tmp);
		}
		
	}

}

 

 

결과

2
4
6
8
-------------------
1
3
5
7
9

 

 

📢 실습(3)

package day09;

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

public class Stream03 {

	public static void main(String[] args) {
		/* Student 클래스로 리스트 구성
		 * Student 이름, 점수만 가지는 클래스
		 * 
		 * 학생 5명을 추가하고, 콘솔에 출력
		 * 홍길동 : 80
		 */
		List<Student> students = new ArrayList<Student>();
		students.add(new Student("홍길동", 80));
		students.add(new Student("홍길순", 90));
		students.add(new Student("김길남", 75));
		students.add(new Student("박영희", 60));
		students.add(new Student("최영숙", 49));
		
		//스트림을 이용하여 콘솔에 출력
		students.stream()
		.forEach(n->System.out.println(n));
		System.out.println("-------------");
		
		//toString이용하지 않고 출력
		students.stream()
		.forEach(n->{
			String name = n.getName();
			int score = n.getScore();
			System.out.println(name+"=>"+score);
		});
		
		System.out.println();
		//students의 점수 합계 / 전체 인원수
		int sum = students.stream()
				.mapToInt(n->n.getScore())
				.sum();
		System.out.println("점수합계:"+sum);
		long count =
				students.stream().count();
		System.out.println("인원수:"+count);
		
		System.out.println("-----------------");
		//이름순으로 정렬하여 출력
		students.stream()
		.sorted(new Comparator<Student>() {
			public int compare(Student o1, Student o2) {
				// o2 => 내림차순
				return o1.getName().compareTo(o2.getName());
			}
			
		}).forEach(System.out::println);
		
		
	}

}

class Student{
	private String name;
	private int score;
	
	public Student() {}
	
	public Student(String name, int score ){
		this.name = name;
		this.score = score;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getScore() {
		return score;
	}

	public void setScore(int score) {
		this.score = score;
	}

	@Override
	public String toString() {
		return name + ":" + score;
	}
	
	
	
	
}

 

 

결과

홍길동:80
홍길순:90
김길남:75
박영희:60
최영숙:49
-------------
홍길동=>80
홍길순=>90
김길남=>75
박영희=>60
최영숙=>49

점수합계:354
인원수:5
-----------------
김길남:75
박영희:60
최영숙:49
홍길동:80
홍길순:90

 

 

📢 실습(4)

package day09;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class StreamEx01 {

	public static void main(String[] args) {
		/* 여행사 상품
		 * 여행비용이 15세 이상은 100만원, 미만은 50만원으로 계산
		 * 
		 * 고객 5명이 패키지 여행을 떠난다고 했을 경우
		 * 1. 비용계산 => 출력
		 * 2. 고객 명단 출력
		 * 고객 클래스를 생성하고, ArrayList로 고객관리
		 * 
		 * 예)
		 * 이름:이순신 나이:40 비용:100
		 * 이름:신사임당 나이:38 비용:100
		 * 이름:홍길동 나이:30 비용:100
		 * 이름:이짱구 나이:10 비용:50
		 * 이름:이짱아 나이:5 비용:50
		 * 총 여행경비 : xxx
		 * 
		 * 20세 이상 고객명단 => 이름순으로 정렬
		 * 이름:이순신 나이:40 비용:100
		 * 이름:신사임당 나이:38 비용:100
		 * 이름:홍길동 나이:30 비용:100
		 * 
		 *  */
		
		List<Customer> ct = new ArrayList<>();
		ct.add(new Customer("이순신", 40));
		ct.add(new Customer("신사임당", 38));
		ct.add(new Customer("홍길동", 30));
		ct.add(new Customer("이짱구", 10));
		ct.add(new Customer("이짱아", 5));
		
		ct.stream()
		.forEach(n->System.out.println(n));
		
		int sum = ct.stream()
		.mapToInt(n->n.getCost())
		.sum();
		System.out.println("총 여행경비:"+sum);
		
		Collections.sort(ct);	// 클래스에 정렬이 구현되어 있을경우 사용가능
		
		System.out.println("--20세 이상(이름 가나다순)--");
		
		ct.stream()
		.filter(n->n.getAge()>=20)
		//Comparator 구현이 없는 경우
//		.sorted(new Comparator<Customer>() {
//
//			@Override
//			public int compare(Customer o1, Customer o2) {
//				return o1.getName().compareTo(o2.getName());
//			}
//			
//		})
		.sorted()	// Comparator를 기존 클래스에서 구현
		.forEach(System.out::println);
		
		//익명클래스 사용할 경우 Comparator 대상값이 (매개변수가 2개)
		//클래스 내부에서 구현할 경우 Comparable 대상값이 (매개변수 1개)

	}

}
class Customer implements Comparable<Customer> {
	//멤버변수 : 각 인원마다 가져야 할 고유 값
	private String name;
	private int age;
	private int cost;
	
	//생성자
	public Customer(String name, int age) {
		this.name = name;
		this.age = age;
		this.cost = age<=15 ? 100 : 50;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getCost() {
		return cost;
	}
	public void setCost(int cost) {
		this.cost = cost;
	}
	
	@Override
	public String toString() {
		return "이름:" + name + " 나이:" + age + " 비용:" + cost ;
	}

	@Override
	public int compareTo(Customer o) {
		// this와 o객체를 정렬
		return this.name.compareTo(o.name);
	}
	
}

 

 

결과

이름:이순신 나이:40 비용:50
이름:신사임당 나이:38 비용:50
이름:홍길동 나이:30 비용:50
이름:이짱구 나이:10 비용:100
이름:이짱아 나이:5 비용:100
총 여행경비:350
--20세 이상(이름 가나다순)--
이름:신사임당 나이:38 비용:50
이름:이순신 나이:40 비용:50
이름:홍길동 나이:30 비용:50

 

'백엔드 > Java' 카테고리의 다른 글

Java 쓰레드(Thread)  (0) 2024.11.13
Java 파일 입출력 (I/O) 처리  (0) 2024.11.04
Java 람다(Lambda)  (0) 2024.10.29
Java 제네릭(Generic)  (1) 2024.10.26
Java로 상품 관리 시스템 구현(2)  (0) 2024.10.25