ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 람다식으로 특정 확장자 파일명 불러오기 (+ forEach()와 향상된 for문)
    JAVA/스트림, 컬렉션 프레임워크, 람다 2024. 6. 7. 12:23

    ▤ 목차

       

       

       

       

      ✔ fileFilter ( 특정 확장자 파일 가져오기 )

      ⌨ 형식

      public class MyLambda3 {
      
      	public MyLambda3() {
      		// 람다 표현식 사용
      		test(); //thread 사용
      	}
          private void test() {
      		//특정 디렉토리(폴더)에 있는 파일 목록 걸러보기
      		File direc = new File("c:/work");
      		
      		//fileFilter 함수형 인터페이스로 람다식 처리, 확장자 txt만 필터링
      		File[] files = direc.listFiles((File file) ->file.isFile() && file.getName().endsWith(".txt"));
      		if(files != null) {
      			for(File f:files) {
      				System.out.println(f.getName());
      			}
      		}
      	}
      
      	public static void main(String[] args) {
      		new MyLambda3();
      	}
      
      }

       

      결과

       

       

       

      👏 endsWith(String suffix)

       

      처음보는 메서드였다.

      문자열이 지정된 접미사(아규먼트로 들어오는 값, 해당 파라미터 값)로 끝나는지 테스트한다.

      endsWith("원하는 확장자")를 적어주면 filtering되어 원하는 확장자 파일이 찍힌다.

       

       

       


       

       

      ✔ Consumer 클래스 명시적 사용

      💻 코드로 보기

      public class MyLambda5Db {
      
      	public MyLambda5Db() {
      		abc();
      	}
      
      	private void abc() {
      		Consumer<Integer> printInt = i -> System.out.println(i);
      
      		List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
      		numbers.forEach(printInt);
      	}
      
      
      	public static void main(String[] args) {
      		new MyLambda5Db();
      
      	}
      
      }

       

      Consumer 인터페이스는 accept()를 가지고 있다. 주로 Collection API의 forEach에서 주로 사용한다.

      위의 코드는 명시적으로 Consumer를 사용했다.

      forEach()의 매개변수 타입이 Consumer이기 때문에 한번더 타입을 만들어 주는 방식이다.

       

       

      💻 Consumer

      함수형 인터페이스이다.

      함수형 인터페이스란 추상메서드를 1개만 가지고 있는 인터페이스를 말한다.

       

      • '소비자' 인터페이스인 이유가 있다. 입력을 받아들인 후 결과를 반환하지 않는다.
      • 수행 할 작업은 consumer 인터페이스를 구현하는 클래스에 포함되어 있으며 forEach에 인수로 전달된다.
      • 1개의 매개변수를 받아들이고 반환값이 없는 추상 메서드인 accept()를 정의 (추상메서드 이름은 안쓴다.)

       

       

      👏 accept()

      추상 메서드이다. 즉 자식 메서드에서 오버라이딩해서 정의해야한다.

       

       

       


      ✔ 향상된 for문과  forEach문 사용

      💻 코드로 보기

      public class MyLambda3 {
      
      	public MyLambda3() {
      		// 람다 표현식 사용
      		test1(); //List 컬렉션을 이용
      		System.out.println("-------");
      	}
      
      	private void test1() {
      		List<String> list = Arrays.asList("Apple","Banana0","Cherry");
      		
      		//전통적인 방법
      		for (String i : list) {
      			System.out.println(i);
      		}
      		
      		// 람다식 사용
      		// forEach는 Consumer 함수형 인터페이스의 인스턴스를 받아 각 요소에 대한 작업을 수행한다.
      		// Consumer : 반환값이 없으며, 1개의 매개변수를 받아들이고 반환값이 없는 추상 메서드인 accept()를 정의 (추상메서드 이름은 안쓴다.)
      		//컬렉션
      		list.forEach(i ->System.out.println(i)); //forEach() for문을 람다식으로 표현
      	}

       

       

       

       

      👏 .asList()

       

       

      지정된 배열이 지원하는 고정 크기 목록을 반환한다. 

      collection.toArray()를 보니 문자열을 복사하여 객체를 생성하는 방식으로 구현된다.

       

       

       

       

       

      🔶 forEach() VS 향상된 for문

      위의 방식은 향상된 for문을 사용한 코드이다.

      값을 가져다 사용만 할 수 있으며 수정이 불가능하다. 역순으로 탐색할 수 없다.

       

      for (String i : list) {
      	System.out.println(i);
      }

       

       

      forEach는 java8에서 추가된 Iterable 인터페이스의 기본 메서드이다.

      Consumer 함수형 인터페이스의 인스턴스를 받아 각 요소에 대한 작업을 수행한다.

      아래는 람다식으로 간편하게 작성한 코드이다.

       

      list.forEach(i ->System.out.println(i));

       

      람다식만 풀어보면 list에 값이 있으면 i 가 파라미터이니, System.out.println으로 i가 콘솔창에 찍힌다.

      forEach()메서드가 반복(loop)을 하고 있는 것이다. 

      즉, 리스트 안에서 내부반복을 하는 메서드이다.

       

      forEach문을사용하는 이유

      원래 인덱스를 사용해서 값을 가져온다. 원하는 인덱스까지 검색하는 시간이 사용된다.
      그러나 forEach문은 iterator를 이용하여 요소를 순회하기 때문에 유연하게 대체가 가능하다.

       

       

      [해석]
      Iterable 모든 요소가 처리되거나 작업에서 예외가 발생할 때까지 각 요소에 대해 지정된 작업을 수행합니다.
      해당 순서가 지정된 경우 작업은 반복 순서대로 수행됩니다. 작업에 의해 발생한 예외는 호출자에게 전달됩니다.
      재정의 클래스가 동시 수정 정책을 지정하지 않은 한 작업이 요소의 기본 소스를 수정하는 부작용을 수행하는 경우 이 메서드의 동작은 지정되지 않습니다.

       consumer 인터페이스를 전달받아 내부적으로 accept()라는 메서드를 실행하는 구조이다.

       

      public class forEachTest {
      	public static void main(String[] args) {
          	list.forEach(new Consumer<String>()(
          		@Override
              	public void accept(String str){
              	  System.out.println(str);
              	}
          	});
      	}
      }

       

      아래와 같이 줄여서 출력이 가능하다.

      list.forEach(System.out::println);

       

       

      단점

      간단한 반복문이라면 함수형 인터페이스가 오래 걸린다.

      Linked List의 경우 일반 for문이 더 오래걸린다.

      ArrayList는 거의 비슷하다. (Array 배열에서 일반 for문이 더 빠르다.)

       

       

      😊정리

      새로운 for문을 배웠다. 반환값이 없는 consumer()를 사용한다. 람다와 함께 많이 사용된다.

      람다식은 무명, 익명클래스를 줄여서 표현할 수 있다. 또한 일회용으로 사용된다.

      forEach()과 람다식을 사용하면 향상된 for문보다 단순하게 표현이 가능하다.

    Designed by Tistory.