[java] 새로운 프로그래밍 방법: 람다식(Lambda Expression)/스트림(Stream)

베뉴·2022년 12월 18일
0

java

목록 보기
1/1
  • 자바는 객체지향 프로그래밍(OOP: Object Oriented Programming)

: 기능을 수행하기 위해서는 객체를 만들고,
객체 내부에 멤버 변수를 선언하고 기능을 구현


1 람다식과 함수형 프로그래밍

💡 람다식(Lambda expression)

  • 함수형 프로그래밍(Functional Programming)
    : 함수의 구현과 호출만으로 프로그래밍이 수행되는 방식
    : 매개변수 만을 사용하여 만드는 함수(함수 외부에 있는 변수를 사용하지 않아 함수가 수행되더라도 외부에 영향을 미치지 않음)


💡 람다식 문법

  • 익명 함수 만들기
  • 매개변수를 이용한 실행문 정의
    (매개변수)->{실행문;}
  • 예시(두 수를 입력받아 더하는 add()함수의 예)
int add(int x, int y) {
	return x + y;
}
  • 람다식으로 표현
(int x, int y) -> {return x+y;}
  • 매개 변수가 하나인 경우 자료형과 괄호도 생략가능 /
str->{System.out.println(str);}

👌 실습을 통해 익히자!

OOP vs Lambda :: 인터페이스 구현

  • 기존의 OOP 방식으로는 인터페이스를 만들면, (1) 인터페이스를 구현한 클래스 (2) 클래스 내부의 메서드 를 통해서 구현했어야 했다.
  • 그러나 람다식 문법을 이용하면,
public interface Add {
	int add(int x, int y);
}
public class AddTest {
	public static void(String[] args) {
    	Add addl = (x, y) -> x+y;
        System.out.println(addl.add(2, 3));
    }
}

💡 함수형 인터페이스(Functional Interface) 사용하기

  • @FunctionalInterface 어노테이션 사용하기
  • 익명 함수와 매개변수만으로만 구현되므로 인터페이스는 단 하나만의 메서드를 선언해야 함
@FunctionalInterface
public interface MyNumber {
	int getMax(int x, int y);
}
  • 람다식의 구현과 호출
public class MyNumberTest {
	public static void main(String[] args) {
    	MyNumber myNumber = (x, y) -> (x >= y)? x : y;
        //x와 y중 더 큰 수를 반환해주는 람다식을 인터페이스 자료형 
        System.out.println(myNumber.getMax(10,20));
    }
 }



❓ 객체지향 프로그래밍 VS 람다식

두 문자열을 매개변수로 받는 StringConcat 인터페이스를 각각의 방식으로 구현해보자.

public interface StringConcat {
	public void makeString(String s1, String s2);
 }

💻 객체지향 프로그래밍 ver.

STEP 1. 인터페이스의 메서드를 구현하는 클래스를 만든다.

public class StringConcatTmpl implements StringConcat {	
    @Override
    public void makeString(String s1, String s2) {
    	System.out.println(s1 + s2);
    }
}

STEP 2. 클래스의 객체를 main에 생성하고, 객체명.메서드()로 함수를 호출한다.

public class StringConcatTest {
	public static void main(String[] args) {
    	StringConCatTmpl strTmpl = new StringConcatTmpl();
        strTmpl.makeString("Hello", "World");
    }
}

💻 람다식 ver.

public class StringConcatTest {
	public static void main(String[] args) {
    	String s1 = "Hello";
        String s2 = "World";  
        StringConcat concat = (s, v)->System.out.println(s+v);
        concat.newString(s1, s2);
     }
 }
  • 람다식은 내부 익명 클래스가 자동적으로 생성되어 만들어진다. 따라서 프로그래머는 클래스를 따로 구현할 필요 없다.
  • 람다식은 매개변수로 전달할 수 있고, 반환 값으로도 쓰일 수 있다.




2 스트림(Stream)

💡 스트림 이란?

  • 자료의 대상과 관계없이 동일한 연산을 수행(배열, 컬렉션을 대상으로 연산을 수행한다.)
  • 일관성 있는 자료처리에 대한 추상화가 구현되었다고 한다.
  • 한 번 생성하고 사용한 스트림은 재사용할 수 없다.
  • 스트림 연산은 기존 자료를 변경하지 않는다.
  • 스트림은 중간 연산과 최종 연산으로 구분된다.

💡 스트림 생성하고 사용하기

  • 정수 배열 받아 합과 갯수 출력하기
public class IntArrayStreamTest {
	public static void main(String[] args) {
		int[] arr= {1, 2, 3, 4, 5};		
		int sumVal = Arrays.stream(arr).sum();
		long count = Arrays.stream(arr).count();		
		System.out.println(sumVal);
		System.out.println(count);
	}
}

💡 중간 연산과 최종 연산


* 중간 연산 : 조건에 맞는 요소를 추출`filter()`하거나 요소를 변환`map()`함. : 중간 연산의 예 - `filter()` `map()` `sorted()` 등
* 최종 연산 : 스트림이 관리하는 자료를 하나씩 소모해가며 연산이 수행됨. ** 최종 연산 후에 스트림은 더 이상 다른 연산을 적용할 수 없음. ** : 최종 연산의 예 - `forEach()` `count()` `sum()` 등 * 최종 연산이 호출될 때 중간 연산이 수행되고 결과가 생성된다.
  • 문자열 리스트에서 문자열의 길이가 5 이상인 요소만 출력하기
sList.stream().filter(s->s.length()>=5).forEach(s->System.out.println(s));
  • 고객 클래스 배열에서 고객 이름만 가져오기
customerList.stream().map(c->c.getName()).forEach(s->System.out.println(s));

💻 ArrayList객체에 스트림 생성하고 사용하기

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

public class ArrayListStreamTest {

	public static void main(String[] args) {
		//List는 추상 클래스, ArrayList가 concrete 클래스
		List<String> sList = new ArrayList<String>();
		sList.add("Thomas");
		sList.add("Edward");
		sList.add("Jack");
		
		Stream<String> stream = sList.stream();
		stream.forEach(s->System.out.println(s));
		
		sList.stream().sorted().forEach(s->System.out.print(s+ "\t"));
		
		System.out.println();
		sList.stream().map(s->s.length()).forEach(n->System.out.print(n+"\t"));
		
		sList.stream().filter(s->s.length()>=5).forEach(s->System.out.println(s));
	}

}
  • 새로운 연산을 수행하기 위해서는 stream() 메서드를 다시 호출해야함.

💻 정수 자료에 대한 여러가지 연산의 예

package ch01;

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

public class IntArrayStreamTest {

	public static void main(String[] args) {
		int[] arr= {1, 2, 3, 4, 5};
		Arrays.stream(arr).forEach(n->System.out.print(n+"\t"));
		System.out.println();
		
		int sum = Arrays.stream(arr).sum();
		System.out.println("sum : "+sum);
		
		List<Integer> list = new ArrayList<Integer>();
		list.add(1); list.add(2); list.add(3);
		list.add(4); list.add(5); list.add(6);
		int sum2= list.stream().mapToInt(n->n.intValue()).sum();
		System.out.println(sum2);

	}

}
profile
백문이불여일타(이전 블로그: https://blog.naver.com/christer10)

0개의 댓글