JAVA_람다식/내부 클래스/스트림

뚱이아저씨·2023년 3월 27일
0

자바

목록 보기
14/15
post-thumbnail
post-custom-banner

람다식

람다식(화살표 함수) 특징

  • 람다식 함수는 익명함수(Anonnymous function)를 지칭하는 용어이다.
  • 함수의 구현과 호출만으로 프로그래밍이 수행 되는 방식
  • 함수형 프로그래밍(Functional Programming : FP)
  • interface를 구현할 class가 따로 없어도 mainmethod에서 사용 가능
  • interface에 추상 메소드가 1개일때만 사용 가능
  • interface만 람다식 구현 가능

람다식 출력 예제

Divide interface

public interface Divide {
	int divide(int x, int y);
}

Mainclass

public class DivideTest {
	public static void main(Stringp[] args) {
    	Divide divide = (int x, int y) -> {return x/y;};
        //원래는 interface이기 때문에 implement 해서 override하고 구현을 해야했는데
        //람다식을 사용하면 implement를 사용해서 바로 구현을 할 수가 있다.
        System.out.println(Divide.divide(10,2));
        
        Divide divide1 = (x,y) -> {return x/y};
        //람다식 표현은 소괄호안에 타입을 지워서 더욱더 간단하게 만들 수 있다.
        
        Divide divide2 = (x,y) -> x/y;
        //실행문이 한 문장인 경우 중괄호도 생략이 가능하다. 대신 중괄호를 생략하면 return 도 생략
    }
}

내부 클래스(Inner class)

내부클래스

  • 클래스 내부에 선언한 클래스(중첩 클래스라고도 한다.)

내부 클래스의 종류

  • 인스턴스 내부 클래스
  • 정적(static) 내부 클래스
  • 지역(local) 내부 클래스(메소드 안에 생성)
  • 익명 내부 클래스(Anonnymous class)

인스턴스 내부 클래스 출력 예시

public class OuterClass {
	private int num=100;
	private static int sNum=200;
	private Innerclass inClass;

	public OuterClass() {inClass=new Innerclass();}

	//클래스안에 또 다른 클래스가 있는 것을 인스턴스 내부 클래스라 한다.
	class Innerclass {
		int inNum=300;

		void showInnerInfo() {
			System.out.println("OuterClass num = "+num);
			System.out.println("OuterClass sNum = "+sNum);
			System.out.println("OuterClass inNum = "+inNum);
		}
	}

	public void callInnerMethod() {inClass.showInnerInfo();}
}

//----------------------------------------------------------------------

public class InnerClassMain {
	public static void main(String[] args) {
		//외부 클래스를 이용하여 내부 클래스의 기능 호출
		OuterClass out=new OuterClass();
		out.callInnerMethod();

		System.out.println();

		//외부클래스의 변수를 이용하여 내부 클래스 생성
		OuterClass.Innerclass inClass=out.new Innerclass();
		inClass.showInneerInfo();
	}
}
  • 인스턴스 내부 클래스는 다른 클래스의 내부에 선언된다.
  • 외부 클래스의 객체가 생성된 후에만 내부 클래스 객체 생성이 가능하다.

내부 클래스의 객체 생성은 다음과 같다

//외부 클래스
OuterClass outer=new OuterClass();
//내부 클래스 생성
OuterClass.InnerClass inner=outer.new InnerClass();

지역 내부 클래스 출력 예시

public class OuterClass {
	int outNum=100;

	Runnable getRunnable(int i) {
		int localNum=200;
		class LocalInner implements Runnable {
			int innerNum=300;
		
			@Override
			public void run() {
				System.out.println("OuterClass의 outNum = " + outNum);
        System.out.println("메소드의 매개변수 i = " + i);
        System.out.println("메소드 안의 num = " + localNum);
        System.out.println("LocalInner의 innerNum = " + innerNum);
			}
		}
		return new LocalInner();
	}
}
  • 지역 내부 클래스는 메소드안에 클래스가 있는 것을 뜻한다.
  • 외부클래스의 객체 생성 후 거기에 있는 메소드를 호출 하여 내부 클래스를 호출 할 수 있다.

지역 내부 클래스 호출은 다음과 같다

public class LocalInnerMain {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
				
        Runnable runnable=out.getRunnable(10);
        runnable.run();
    }
}

익명 내부 클래스 출력 예시

class OuterClass {
	Runnable getRunnable() {
		return new Runnable() { //익명 내부 클래스
			@Override
			public void run() {System.out.println("Runnable Class");}
		};
	}
}

public class AnonymousInnerMain {
	public static void main(String[] args) {
		OuterClass out=new OuterClass();
		out.getRunnable();

		Runnable runnable = out.getRunnable();
		runnable.run();
	}
}
  • 익명 내부 클래스는 원래 람다식의 원시적인 클래스 생성 방법이다.

스트림(Stream)

스트림의 정의

  • 자료의 대상과 상관없이 동일한 연산을 수행
  • 한번 생성하고 사용한 스트림은 재사용할 수 없음
    (다른 연산을 수행하기 위해서는 스트림을 다시 생성해야 함)
  • 스트림 연산은 기존 자료를 변경하지 않음

stream은 재사용할 수 없다. 출력 예시

public class IntArrayStreamTest {
	public static void main(String[] args) {
		int[] ints={1,2,3,4,5};

		IntStream is=Arrays.stream(ints); //IntStream 객체 생성
		is.forEach(i -> System.out.println(i));

		//int sum=is.sum(); 스트림은 이미 한번 사용을 했기 때문에 재 사용 할 수없다.
		//새로운 객체를 생성 후 사용해줘야 한다.
		int sum=Arrays.stream(ints).sum();
		System.out.println(sum);
	}
}

stream().sum() / stream().count() 출력예시

public class IntArrayStreamTest {
	public static void main(String[] args) {
		int[] ints={1,2,3,4,5};

		//stream을 사용하여 배열의 합을 구하려면 sum을 사용하면 된다.
		int sum=Arrays.stream(ints).sum();

		//count는 배열안에 있는 원소의 개수를 구하는 것이다.
		long count=Arrays.stream(ints).count();

		System.out.print(sum); //15
		System.out.print(count); //5
	}
}

stream().sorted() / stream().map() 출력예시

public class ArrayListStreamTest {
    public static void main(String[] args) {
			ArrayList<String> list=new ArrayList<>();
			//ArrayList는 collection framwork이다.
			//<>방을 의미한다 즉, <String>은 String 타입의 배열(방)을 말한다.

			list.add("Arine");
			list.add("Pancho");
			list.add("Jake");

			Stream<String> stream=list.stream();
			stream.forEach(s -> System.out.print(s + "\t");

			System.out.println();

			//중간 연산_최종 연산
			//sorted()는 알파벳 순서대로 단어를 정렬하는 기능을 가지고 있다.
			list.stream().sorted().forEach(s -> System.out.print(s+"\t"));
			
			//map은 각 배열의 길이의 개수를 표현한다. Arine는 5, Pancho는 6, Jake는 4 이다.
			list.stream().map(m -> m.length()).forEach(s -> System.out.println(s+|\t));
			
	}
}
  • 메소드 체이닝을 이용해 여러 개의 메소드(연산)을 한꺼번에 사용가능
    - 1) 중간연산 : 여러 개의 연산이 적용될 수 있음
    • 예) filter(), map(), sorted()
    • 2) 최종 연산 : 마지막에 한 번만 적용됨
    • 예) forEach(), count(), sum()
    • 최종 연산이 호출되어야 중간 연산에 대한 수행이 이루어짐
    • 중간연사에 대한 결과를 초종연산 수행 전까지는 알 수 없음(자연 연산)
profile
뚱이아빠의 개발자도전기
post-custom-banner

0개의 댓글