람다식

 

Map 함수형인터페이스로 값 출력하기

// Map
		Map<String, String> map = new HashMap<String, String>();
		map.put("1", "1");
		map.put("2", "2");
		map.put("3", "3");
		map.put("4", "4");

		// iterator 방식
		Iterator<Map.Entry<String, String>> entries = map.entrySet().iterator();

		while (entries.hasNext()) {
			Map.Entry<String, String> entry = entries.next();
			System.out.println("key : " + entry.getKey() + ", value :" + entry.getValue());
		}

		System.out.println();

		// 향상된 for문
		for (Map.Entry<String, String> entry : map.entrySet()) {
			System.out.println("key : " + entry.getKey() + ", value :" + entry.getValue());
		}
		
		System.out.println();
		
		// 함수형 인터페이스
		map.forEach((k,v) -> System.out.println(k + "," + v));

이어서 람다식을 사용해본다.

 

java.util.function 패키지 예제

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class LambdaTest4 {

	public static void main(String[] args) {
		Supplier<Integer> s = () -> (int) (Math.random() * 100) + 1;
		Consumer<Integer> c = i -> System.out.print(i + ", ");
		Predicate<Integer> p = i -> i % 2 == 0;
		Function<Integer, Integer> f = i -> i / 10 * 10; // i의 일의 자리를 없앤다.

		List<Integer> list = new ArrayList<>();
		makeRandomList(s, list);
		System.out.println(list);
		printEvenNum(p, c, list);
		List<Integer> newList = dosomthing(f, list); 
		System.out.println(newList);

	}

	// 메소드의 매개변수를 제한할 떄 제네릭 타입 사용하기
	// list에 나온 수들의 1의 자리를 없앤 값 newList에 넣기
	static <T> List<T> dosomthing(Function<T, T> f, List<T> list) {
		// ArrayList는 사이즈를 지정하지 않아도 기본 크기가 10
		// 크기를 지정해두면 속도가 좋아진다
		List<T> newList = new ArrayList<T>(list.size());

		for (T i : list) {
			newList.add(f.apply(i));
		}

		return newList;
	}

	// list에서 짝수만 출력하기
	static <T> void printEvenNum(Predicate<T> p, Consumer<T> c, List<T> list) {
		System.out.print("[");
		
		for (T i : list) {
			if (p.test(i)) {
				c.accept(i);
			}
		}
		System.out.println("]");
	}

	// 100 이하의 랜덤 수 10개를 list에 넣기
	static <T> void makeRandomList(Supplier<T> s, List<T> list) {
		for (int i = 0; i < 10; i++) {
			list.add(s.get());
		}
	}
}

 

람다식의 메소드 참조 방식 (매개변수 생략, ::)

import java.util.function.BiFunction;
import java.util.function.Function;

public class LambdaTest5 {

	public static void main(String[] args) {
		// 람다식의 메소드 참조 방식 (매개변수 생략, ::)
		// 람다식이 하나의 메소드만 호출하는 경우에는 메소드 참조라는 방식으로 호출할 수 있다.

		// 문자열을 정수로 바꿔준다
		// Function<String, Integer> f = s -> Integer.parseInt(s);
		Function<String, Integer> f = Integer::parseInt; // 메소드 참조
		int i = f.apply("100");
		System.out.println(i + 100);

		// BiFunction<String, String, Boolean> f2 = (s1, s2) -> s1.equals(s2); 
		// 문자열이 같은지 비교
		BiFunction<String, String, Boolean> f2 = String::equals; // 메소드 참조
		boolean b = f2.apply("hello", "hello"); // 문자열이 같다
		System.out.println(b); // 문자열이 같으므로 true

	}

}

 

 

System.out.println() 의 메소드 참조 방식 

 // BiFunction<String, String, Boolean> f2 = (s1, s2) -> s1.equals(s2); // 문자열이 같은지 비교
		BiFunction<String, String, Boolean> f2 = String::equals; // 메소드 참조
		boolean b = f2.apply("hello", "hello"); // 문자열이 같다
		System.out.println(b); // 문자열이 같으므로 true
		
		ArrayList<Integer>list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		
		//list.forEach(i -> System.out.println(i));
		list.forEach(System.out :: println);

많이 쓴다!!

위 코드들은 베이스 코드. 응용에 앞서 베이스코드를 혼자 짤 수 있어야 한다.

대표하는 베이스 코드는 머리 속에 넣어둬야 한다. → 그냥 외워

 

Stream

: 데이터를 추상화(표준화) 하여 사용하기 편하게 연산하는 방식을 통일한다

 

배열을 스트림화

package Stream0529;

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

public class StreamTest {
	
	// Stream
	// 객체형식으로 되어있는 데이터를 다루는 변수 구조 : 배열, 컬렉션
	// 데이터를 추상화(표준화) 하여 사용하기 편하게 연산하는 방식을 통일한다
	// 중간연산, 최종연산
	
	// 배열을 스트림화 하는 3가지 방식
	
	Stream<String> stream1 = Stream.of("a", "b", "c"); // 가변인자
	Stream<String> stream2 = Stream.of(new String[] {"a", "b", "c"}); // 직접입력
	Stream<String> stream3 = Arrays.stream(new String[] {"a", "b", "c"}); // Arrays 사용
	
	// 기본형에 IntStream 으로 스트림화 하기
//	IntStream IntStream.of(int ...value);
//	IntStream intStream.of(int[]);
//	IntStream Arrays.stream(int[]);
			

}

 

연산자 : map(), filter(), distinct(). forEach() 사용

package Stream0529;

import java.io.File;
import java.util.stream.Stream;

public class StreamTest2 {

	public static void main(String[] args) {
		File[] fileArr = { new File("Ex1.java"), new File("Ex1.bak"), new File("Ex2.java"), new File("Ex1"),
				new File("Ex1.txt") };

//		File f1 = fileArr[0];
//		System.out.println(f1.getName()); // Ex1.java

		Stream<File> fileStream = Stream.of(fileArr);

		Stream<String> filenameStream = fileStream.map(File::getName);
		filenameStream.forEach(System.out::println);

		// 스트림을 다시 생성해서 초기상태로 만들어야한다.
		fileStream = Stream.of(fileArr);

		// 연산자 : map(), filter(), distinct(). forEach() 사용
		fileStream.map(File::getName) // Stream<File> -> Stream<String>
				.filter(s -> s.indexOf('.') != -1) // 확장자가 없는 것은 제외
				.map(s -> s.substring(s.indexOf('.') + 1)) // 확장자만 유출
				.map(String::toUpperCase) // 모두 대문자로 변환
				.distinct() // 중복제거
				.forEach(System.out::print); // JAVABAKTXT

		System.out.println();

	}

}

 

기본형을 스트림화

package Stream0529;

import java.util.stream.IntStream;

public class StreamTest3 {
	public static void main(String[] args) {

		IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
		intStream.forEach(System.out::println);

		System.out.println("============");
		IntStream.range(1, 5).forEach(System.out::println); // 마지막은 포함하지 않는다

		System.out.println("============");
		IntStream.rangeClosed(1, 5).forEach(System.out::println); // 마지막까지 포함된다

		System.out.println("============");
		IntStream.rangeClosed(1, 5).map(n -> n * n).filter(n -> n % 2 == 0).forEach(System.out::println);

		// sum(), average(), max(), min()

		System.out.println("============");

		// 1부터 5까지의 합
		int sum = IntStream.rangeClosed(1, 5).sum();
		System.out.println(sum);

		// 1부터 5까지의 합의 평균 구하기
		// getAsDouble() 실수형으로 값을 바꿔준다
		double avg = IntStream.rangeClosed(1, 5).average().getAsDouble();
		System.out.println(avg);

		// 최대값 구하기
		int max = IntStream.rangeClosed(1, 5).max().getAsInt();
		System.out.println(max);

		// 최소값 구하기
		int min = IntStream.rangeClosed(1, 5).min().getAsInt();
		System.out.println(min);

		// anyMatch()
		// 스트림의 요소 중 어느 하나라도 주어진 술어를 만족하면 'true'를 반환
		boolean any = IntStream.rangeClosed(1, 5).anyMatch(n -> n == 7);
		System.out.println(any);

	}
}

 

 

스트림 정렬

기본정렬 방식에 대한 정의가 클래스 안에 되어있어야 한다!

String 안에 기본 정렬(오름차순)이 있었던 것처럼!

 

정렬에 대해 복습하며 제네릭으로 바꿔보기)

더보기

제네릭

 

제네릭 적용 전

package come.list;

import lombok.AllArgsConstructor;
import lombok.ToString;

@AllArgsConstructor
@ToString
public class Student implements Comparable {
	String name;
	int ban;
	int no;
	int kor, eng, math;

	int getTotal() {
		return kor + eng + math;
	}

	float getAverage() {
		return (int) ((getTotal() / 3f) * 10 + 0.5) / 10f;
	}

	// 학생의 이름에 따라 정렬
	@Override
	public int compareTo(Object o) { // Object o -> Student

		if (o instanceof Student) {
			Student other = (Student) o; // 값으로 가지고 와서 사용할 수 있다.

			// return this.no - other.no; // 오름차순
			// return other.no - this.no; // 내림차순
			return this.name.compareTo(other.name); // 오름차순
			// return this.name.compareTo(other.name) * -1; // 내림차순
		}
		return -1;
	}
}

 

 

제네릭 적용 후

public class Student implements Comparable<Student> {
	String name;
	int ban;
	int no;
	int kor, eng, math;

	int getTotal() {
		return kor + eng + math;
	}

	float getAverage() {
		return (int) ((getTotal() / 3f) * 10 + 0.5) / 10f;
	}

	// 학생의 이름에 따라 정렬
	@Override
	public int compareTo(Object o) { // Object o -> Student

			return this.name.compareTo(s.name); // 오름차순
			
		}
}

 

 

 

스트림으로 정렬해보기

package Stream0529;

public class Student implements Comparable<Student>{
	
	String name;
	int ban;
	int totalScore;

	public Student(String name, int ban, int totalScore) {
		this.name = name;
		this.ban = ban;
		this.totalScore = totalScore;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", ban=" + ban + ", totalScore=" + totalScore + "]";
	}
	
	String getName() {
		return name;
	}
	
	int getBan() {
		return ban;
	}
	
	int getTotalScore() {
		return totalScore;
	}
	
	@Override
	public int compareTo(Student s) {
		// TODO Auto-generated method stub
		return s.totalScore - this.totalScore; // 총점으로 내림차순
	}

}
package Stream0529;

import java.util.Comparator;
import java.util.stream.Stream;

public class StreamTest4 {

	public static void main(String[] args) {
		// 가변형 방식의 스트림
		
		Stream<Student> studentStream = Stream.of(
				new Student("남파이", 3, 142),
				new Student("강자바", 3, 298),
				new Student("최타임", 2, 90),
				new Student("코틀린", 5, 273),
				new Student("크립트", 7, 194),
				new Student("이루비", 2, 210),
				new Student("안쿼리", 1, 198)
				);
		
		//studentStream.sorted(Comparator.comparing((Student s) -> s.getBan()))
		studentStream.sorted(Comparator.comparing(Student::getBan))
		.forEach(System.out::println);

	}

}

 

결과 :

Student [name=안쿼리, ban=1, totalScore=198]
Student [name=최타임, ban=2, totalScore=90]
Student [name=이루비, ban=2, totalScore=210]
Student [name=남파이, ban=3, totalScore=142]
Student [name=강자바, ban=3, totalScore=298]
Student [name=코틀린, ban=5, totalScore=273]
Student [name=크립트, ban=7, totalScore=194]

반을 기준으로 오름차순 되어 나온다.

+ Recent posts