반응형

컬렉션 프레임워크(collection framework)란?

  • 자바에서 컬렉션 프레임워크(collection framework)란 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미합니다
  • 즉, 데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓은 것입니다.
  • 이러한 컬렉션 프레임워크는 자바의 인터페이스(interface)를 사용하여 구현됩니다.

컬렉션 프레임워크 주요 인터페이스

  • 컬렉션 프레임워크에서는 데이터를 저장하는 자료 구조에 따라 다음과 같은 핵심이 되는 주요 인터페이스를 정의하고 있습니다.
    1. List 인터페이스
    2. Set 인터페이스
    3. Map 인터페이스
  • 이 중에서 ListSet인터페이스는 모두 Collection 인터페이스를 상속받지만, 구조상의 차이로 인해 Map인터페이스는 별도로 정의됩니다.
  • 따라서 List인터페이스와 Set인터페이스의 공통된 부분을 Collection 인터페이스에서 정의하고 있습니다.

주요 인터페이스 간의 상속 관계

자바에서 컬렉션 프레임워크를 구성하고 있는 인터페이스 간의 상속 관계는 다음 그림과 같습니다.

위의 그림에서 <E>나 <K, V>라는 것은 컬렉션 프레임워크를 구성하는 모든 클래스가 제네릭으로 표현되어 있음을 알려줍니다.

제네릭의 개념에 대한 더 자세한 사항은 자바 제네릭 수업에서 확인할 수 있습니다.

주요 인터페이스의 간략한 특징

자바에서 컬렉션 프레임워크를 구성하고 있는 주요 인터페이스의 간략한 특징은 다음과 같습니다.

인터페이스 설명 구현 클래스
List<E> 순서가 있는 데이터의 집합으로, 데이터의 중복을 허용함. Vector, ArrayList, LinkedList, Stack, Queue
Set<E> 순서가 없는 데이터의 집합으로, 데이터의 중복을 허용하지 않음. HashSet, TreeSet
Map<K, V> 키와 값의 한 쌍으로 이루어지는 데이터의 집합으로, 순서가 없음.
이때 키는 중복을 허용하지 않지만, 값은 중복될 수 있음.
HashMap, TreeMap, Hashtable, Properties

컬렉션 클래스(collection class)

  • 컬렉션 프레임워크에 속하는 인터페이스를 구현한 클래스를 컬렉션 클래스(collection class)라고 합니다.
  • 컬렉션 프레임워크의 모든 컬렉션 클래스는 List와 Set, Map 인터페이스 중 하나의 인터페이스를 구현하고 있습니다.
  • 또한, 클래스 이름에도 구현한 인터페이스의 이름이 포함되므로 바로 구분할 수 있습니다.
  • Vector나 Hashtable과 같은 컬렉션 클래스는 예전부터 사용해 왔으므로, 기존 코드와의 호환을 위해 아직도 남아 있습니다.
  • 하지만 기존에 사용하던 컬렉션 클래스를 사용하는 것보다는 새로 추가된 ArrayList나 HashMap 클래스를 사용하는 것이 성능 면에서도 더 나은 결과를 얻을 수 있습니다.
  • 다음 예제는 ArrayList클래스를 이용하여 리스트를 생성하고 조작하는 예제입니다.
import java.util.*;

public class Collection01 {
    public static void main(String[] args) {
        // 리스트 생성
        ArrayList<String> arrList = new ArrayList<String>();

        // 리스트에 요소의 저장
        arrList.add("넷");
        arrList.add("둘");
        arrList.add("셋");
        arrList.add("하나");
 
        // 리스트 요소의 출력
        for(int i = 0; i < arrList.size(); i++) {
            System.out.println(arrList.get(i));
        }
    }
}

실행 결과

Collection 인터페이스

  • List와 Set인터페이스의 많은 공통된 부분을 Collection 인터페이스에서 정의하고, 두 인터페이스는 그것을 상속받습니다. 따라서 Collection 인터페이스는 컬렉션을 다루는데 가장 기본적인 동작들을 정의하고, 그것을 메소드로 제공하고 있습니다.
  • Collection 인터페이스에서 제공하는 주요 메소드는 다음과 같습니다.
메소드 설명
boolean add(E e) 해당 컬렉션(collection)에 전달된 요소를 추가함. (선택적 기능)
void clear() 해당 컬렉션의 모든 요소를 제거함. (선택적 기능)
boolean contains(Object o) 해당 컬렉션이 전달된 객체를 포함하고 있는지를 확인함.
boolean equals(Object o) 해당 컬렉션과 전달된 객체가 같은지를 확인함.
boolean isEmpty() 해당 컬렉션이 비어있는지를 확인함.
Iterator<E> iterator() 해당 컬렉션의 반복자(iterator)를 반환함.
boolean remove(Object o) 해당 컬렉션에서 전달된 객체를 제거함. (선택적 기능)
int size() 해당 컬렉션의 요소의 총 개수를 반환함.
Object[] toArray() 해당 컬렉션의 모든 요소를 Object 타입의 배열로 반환함.

[참고 자료]

http://www.tcpschool.com/java/java_collectionFramework_concept

반응형
반응형

람다식 표현

람다식 표현이란?

함수( 매서드 )를 간단한 식(expression)으로 표현하는 방법

int max(int a, int b){
    return a > b ? a : b;	 //  >>>	(a, b) -> a > b ? a : b
}

익명 함수(이름이 없는함수, anonymous function)

int max(int a, int b) -> { return a > b ? a : b; }

함수와 매서드의 차이

  • 근본적으로 동일. 함수는 일반적 용어, 매서드는 객체지향개념 용어
  • 함수는 클래스에 독립적, 매서드는 클래스에 종속적

람다식 작성하기

① 매서드의 이름과 반환 타입을 제거하고 '->'를 블록{} 앞에 추가한다.

int max(int a, int b){		
	return a > b ? a : b;	
}
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
(int a, int b) -> {		
	return a > b ? a : b;	
}

② 반환 값이 있는 경우, 식이나 값만 적고 return문 생략 가능 (끝에 ';' 안붙임)

(int a, int b) -> {		
	return a > b ? a : b;	
}
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
(int a, int b) -> a > b ? a : b

③ 매개변수의 타입이 추론 가능하면 생략 가능(대부분의 경우 생략 가능)

(int a, int b) -> a > b ? a : b
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
(a,  b) -> a > b ? a : b

※ 주의 사항

1. 매개변수가 하나인 경우, 괄호() 생략가능(타입이 없을 때만)

// (a) -> a * a
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
a -> a * a // 문제 없음

// (int a) -> a * a
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
int a -> a * a // 에러

2. 블록 안의 문장이 하나 뿐 일 때, 괄호{}생략 가능 (끝에 '';" 안 붙임)

(int i) -> {	
	System.out.println(i);
}
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
(int i) -> System.out.println(i)

3. 단, 하나 뿐인 문장이 return문이면 괄호{} 생략 불가

(int a, int b) -> { return a > b ? a : b; } // OK
(int a, int b) -> return a > b ? a : b      // 에러 발생

함수형 인터페이스

람다식은 익명 함수가 아니라 익명 객체이다.

( a, b ) -> a > b ? a : b
// 위의 람다식은 밑과 같이 적혀있는것과 비슷하다
new Object(){
	int max(int a, int b){
		return a > b ? a : b;
	}
}

람다식(익명 개체)을 다루기 위한 참조 변수가 필요. 참조 변수의 타입은?

Object obj = new Object(){		
	int max(int a, int b){	
		return a > b ? a : b;
	}
};
// 위와같이 정의한뒤 밑과 같이 사용하려고 해도 에러가 발생한다.
// 위에 정의한 max 메소드는 Object클래스에 정의되어 있지 않기 떄문에 에러가 발생함
int value = obj.max(3, 5);

타입 obj = ( a, b ) -> a > b ? a : b;

  • Object 타입은 람다식 표현을 입력할 수 없다. 그렇기 때문에 함수형 인터페이스를 이용해서 람다식을 사용한다.

함수형 인터페이스

단 하나의 추상 메서드만 선언된 인터페이스

@FunctionalInterface
interface MyFunction{
    public abstract int max(int a, int b);
}

// 익명클래스 클래스의 선언, 객체 생성 동시에 진행됨
MyFunction f = new MyFunction() {
        public int max(int a, int b){
            return a > b ? a : b;
        }
    };
                    
int value = f.max(3, 5); // OK, MyFunction에 max() 가 있음

함수형 인터페이스 타입의 참조 변수로 람다식을 참조할 수 있음

MyFunction f = (a, b) -> a > b ? a : b;
int value = f.max(3, 5); // 실제로는 람다식(익명 함수)이 호출됨
/*
//Ex1)
List<String> list = Arrays.asList("abc","aaa","bbb","ddd","aaa");

Collections.sort(list, new Comparator<String>(){
            public int compare(String s1, String s2) -> {            
                return s2.compareTo(s1);        
            }            
        });                

@FunctionalInterface
interface Comparator<T>{
    int compare(T o1, T o2);
}
*/                
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //

List<String> list = Arrays.asList("abc","aaa","bbb","ddd","aaa");

Collections.sort(list, (s1,  s2) - > s2.compareTo(s1));

@FunctionalInterface
interface Comparator<T>{
    int compare(T o1, T o2);
}

함수형 인터페이스 타입의 매개변수, 반환 타입

// 함수형 매개변수    
// 함수형 인터페이스를 인수로 받는다는건 람다식 메소드을 받겠다는 이야기     
void aMethod( MyFunction f ){    
    f.myMethod(); // MyFunction에 정의된 매서드 호출
}    
    
@FunctionalInterface    
interface Comparator<T>{    
    int compare(T o1, T o2);
}    
    
MyFunction f = () -> System.out.println("myMethod()");
aMethod(f);    
// ↓ 메소드를 읽기전에 람다식을 직접 입력해주는 형태도 가능
aMethod(() -> System.out.println("myMethod()"));
// 함수형 반환타입
/*
MyFunction myMethod(){
	MyFunction f = () -> {};
	return f;
}
*/
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
MyFunction myMethod(){	
	return () -> {};
}

[참고 자료]

[자바의 정석 - 기초편] ch14-1~4 람다식이란? 람다식 작성하기

[자바의 정석 - 기초편] ch14-5,6 함수형인터페이스

반응형
반응형

익명 클래스 (anonymous class)

익명 클래스란?

  • 익명 클래스(anonymous class)란 다른 내부 클래스와는 달리 이름을 가지지 않는 클래스를 의미
  • 익명 클래스는 클래스의 선언과 동시에 객체를 생성하므로, 단 하나의 객체만을 생성하는 일회용 클래스
new 조상클래스이름(){
	// 멤버 선언	
}

// 혹은

new 구현인터페이스이름() {
	// 멤버 선언	
}
  • 자기 이름을 못 쓰고 조상클래스의 이름을 쓴다.
  • 혹은 interface를 사용한다.
  • 익명클래스라서 클래스 이름을 사용하지 못한다.
// Ex1) Object 익명클래스인 경우

class Ex7_17{
    Object iv = new Object(){ void method(){ …. } };                       // 익명 클래스    
    static Object cv = new Object(){ void method(){ …. } };                // 익명 클래스    

    void myMethod(){                                
        Object lv = new Object(){ void method(){ …. } };                   // 익명 클래스    
    }
}
// Ex2) AWT( 자바의 윈도우 프로그램 ) 의 경우 (익명클래스가 아닌경우)

import java.awt.*;
import java.awt.event.*;

class Ex7_18 {
    public static void main(String[] args){
        Button b = new Button("Start");
        b.addActionListener(new EventHandler());
        // ②객체 생성
    }
}

// ①클래스 정의
class EventHandler implements ActionListener{
    public void actionPerformed( ActionEvent e ){
        System.out.println("ActionEvent occurred!!!");
    }
}

대부분 Ex2와 같은 경우에는 클래스를 1회성으로 사용되기 때문에 따로 클래스 정의할 필요가 없고 익명클래스화 시켜서 사용한다.

import java.awt.*;
import java.awt.event.*;

class Ex7_18 {
    public static void main(String[] args){
        Button b = new Button("Start");

// 조상 또는 인터페이스 이름을 입력한뒤 필요한 처리를 입력한다
// 클래스의 정의와 객체 생성을 동시에 처리한다
        b.addActionListener(new ActionListener(){
            public void actionPerformed( ActionEvent e ){
                System.out.println("ActionEvent occurred!!!");
            }
        });
    }
}

[자바의 정석 - 기초편] ch7-51,52 익명 클래스

 

반응형
반응형

이너 클래스(내부 클래스)

이너 클래스란?

1. 내부 클래스(inner class)란 하나의 클래스 내부에 선언된 또 다른 클래스를 의미합니다. 이러한 내부 클래스는 외부 클래스(outer class)에 대해 두 개의 클래스가 서로 긴밀한 관계를 맺고 있을 때 선언할 수 있습니다.

 

※ 일반적인 클래스

class A{		 		
	…			
}				
class B{				
	…	      // A를 사용하기 위해서는		
}		      // A의 객체를 생성해야한다.

※ 내부 클래스가 포함된 형태

class A{			// B의 외부 클래스
	…		
    class B{		// 내부 클래스
    // 객체생성 없이도 A의 멤버접근가능
    	…	
    }		
	…		
}

2. 내부클래스의 장점

  • 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
  • 코드의 복잡성을 줄일 수 있다. (캡슐화)

이너 클래스의 특징

1. 외부 클래스의 인스턴스를 먼저 생성해야 인스턴스 클래스의 인스턴스를 생성가능하다

    ① class B에서 class A의 객체를 생성해야 사용 가능

    ② class A의 객체를 만들지 않아도 class B에서 class A의 객체를 쓸 수 있다.

    ③ BBB클래스에서 b객체를 사용하려면 또 AAA클래스에서 b객체를 만들어야 한다.

    ④ BBB클래스는 AAA안에서만 사용한다는 가정하에 inner class로 선언한 것

// Ex1)
class AAA{								
    int i = 100;							
    BBB b = new BBB();							
}								
								
class BBB{								
    void method(){							
        AAA a = new AAA();	        // ①
        System.out.println(a.i);	// ①
    }							
}								
								
class CCC{								
    BBB b = new BBB();							
}								
								
public class InnerTest{								
    public static void main(String args[]){							
        BBB b = new BBB();						
        b.method();						
    }							
}
// Ex2)
class AAA{		// AAA는 BBB의 외부 클래스
    int i = 100;
    BBB b = new BBB();		// ③

    class BBB{		// BBB는 AAA의 내부 클래스
        void method(){
            AAA a = new AAA();
            System.out.println(a.i);
        }
    }
}

// BBB클래스가 내부 클래스로 선언 되었기 때문에 에러 발생
class CCC{
    BBB b = new BBB();
}

// BBB클래스가 내부 클래스로 선언 되었기 때문에 에러 발생
public class InnerTest{
    public static void main(String args[]){
        BBB b = new BBB();
        b.method();
    }							
}
// Ex3)
class AAA{                               // AAA는 BBB의 외부 클래스
    int i = 100;
    BBB b = new BBB();                   //    ③

    // BBB는 AAA의 내부 클래스
    class BBB{                           //    ④
        void method(){                   //    ④
//            AAA a = new AAA();                   //    ④
//            System.out.println(a.i);             //    ④
// 객체 생성없이 외부 클래스의 멤버 접근가능          //    ④
            System.out.println(i);       //    ②④
        }                                //    ④
    }                                    //    ④
}

// BBB클래스가 내부 클래스가 되었기 때문에 CCC 에러 발생
class CCC{
    BBB b = new BBB();
}

// BBB클래스가 내부 클래스가 되었기 때문에 에러 발생
public class InnerTest{
    public static void main(String args[]){
        BBB b = new BBB();
        b.method();
    }
}
// 여기서 main에서 내부클래스의 BBB 객체는 생성할수 없다.
// 내부클래스는 외부클래스를 먼저 생성한 다음에야 생성이 가능하기 때문
// BBB클래스는 AAA의 멤버처럼 다루어 진다.

이너 클래스의 종류와 특징

이너 클래스의 종류와 유효범위(scope)는 변수와 동일

// 변수인 경우
class Outer{
    int iv = 0;                // ①
    static int cv = 0;        // ②
            
    void myMethod(){
        int lv = 0;            // ③
    }
}
//내부 클래스인 경우
class Outer{
    class InstanceInner{ … }          // ①
    static class StaticInner{ … }    // ②
            
    void myMethod(){        
        class LocalInner{ ... }        // ③
    }
}
이너 클래스 특징
인스턴스 클래스 (instance class) ① 외부클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 인스턴스멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적으로 선언된다.
인스턴스 클래스 (instance class) ② 외부 클래스의 멤버변수 선언위치에 선언하며, 외부클래스의 static멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static메서드에서 사용될 목적으로 선언된다.
인스턴스 클래스 (instance class) ③ 외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다.
익명 클래스 (anonymous class) 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용)

이너 클래스의 제어자와 접근성

이너 클래스의 제어자는 변수에 사용 가능한 제어자와 동일

※ 원래 클래스의 접근제어자(modifier)에는 default와 public 밖에 안됐는데 이너 클래스의 접근제어자에는

public, default, private, protected 모두 사용가능

static 멤버란

    객체 생성 없이 사용가능 한 것

    이너 클래스를 작성하는데 static 멤버가 필요하다면?

    이너 클래스도 static 이너 클래스가 되어야 한다.

// Ex4)
/* 다른 class는 객체를 만들어야만 변수를 사용하는데 그 class안에 static변수가 
// 존재하는건 불가능하다
*/
class Ex7_12 { 
    // static클래스 이외에서는 static변수를 선언할수 없다
    // final static은 상수이므로 허용
    class InstanceInner {
        int iv = 100;
//      static int cv = 100;
        final static int CONST = 100;
    }

// static클래스만 static멤버를 정의할 수 있다.
// static class 안에서만 static int cv 같은 변수를 만들 수 있다.
    static class StaticInner{
        int iv = 200;
        static int cv = 200;
    }

    // static클래스 이외에서는 static변수를 선언할수 없다
    // final static은 상수이므로 허용
    void myMethod(){
        class LocalInner{
            int iv = 300;
//          static int cv = 300;
            final static int CONST = 300;
        }
    }
}

※ static 내부 클래스에서는 외부 클래스의 인스턴스 멤버에 접근할 수 없다.

※ 다만 상수(final)인 경우에는 이너 클래스가 static 멤버를 가질 수 있다.

상수(상수≠변수)인 경우에는 inner class가 static 멤버를 가질수 있다.

※ 지역 내부 클래스는 메서드 내에서만 접근 가능하다.

method()안의 LocalInner class는 그 method() 안에서만 접근 가능하다.
// Ex5)
// Ex4) 이어서

public static void main(String args[]){
    System.out.println(InstanceInner.CONST);    // 가능
    System.out.println(StaticInner.cv); // 가능
    System.out.println(LocalInner.CONST); // 에러 지역 내부 클래스는 메서드 내에서만
}
// Ex6) 내부 클래스의 제어자와 접근성 예제

class Ex7_13 {
    class InstanceInner{ …. }
    static class StaticInner{ …. }

    InstanceInner iv = new InstanceInner(); // instance 멤버끼리는 직접 접근 가능
    static StaticInner cv = new StaticInner(); // static 멤버끼리는 직접 접근 가능
        
    static void staticMethod(){    // static멤버는 instance멤버에 직접 접근 불가
//      InstanceInner obj1 = new InstanceInner();
        static StaticInner cv = new StaticInner();

        // instance 클래스는 외부 클래스를 먼저 생성해야 생성가능
        Ex7_13 outer = new Ex7_13();
        InstanceInner obj1 = outer.new InstanceInner();
    }

    // instance메서드에서는 instance멤버와 static멤버 모두 접근 가능
    void instanceMethod(){
        InstanceInner obj1 = new InstanceInner();
        static StaticInner cv = new StaticInner();
        // 지역 내부 클래스는 외부에서 접근할 수 없다.
        //localInner lv = new LocalInner();
    }

    void myMethod(){
        class LocalInner{ …. }
        LocalInner lv = new LocalInner();
    }
}
// Ex7) 내부 클래스의 제어자와 접근성 예제

class Outer { 
    private int outerIv = 0;
    static int outerCv = 0;

    class InstanceInner{
        // 외부 클래스의 private멤버도 접근가능하다.
        int iiv = outerIv;
        int iiv2 = outerCv;
    }        

    static class StaticInner {
//  static 클래스는 외부 클래스의 instance 멤버에 접근할 수 없다.
//    int siv = outerIv;
        static int scv = outerCv;
    }

    void myMethod(){        
        int lv = 0;    
        final int LV = 0;        // JDK1.8 부터 final 생략 가능

        class LocalInner{    
            int liv = outerIv;
            int liv2 = outerCv;

// 외부 클래스의 지역변수는 final이 붙은 변수(상수)만 접근가능하다.
//          int liv3 = lv;        // 에러
            int liv4 = LV;        // Ok
        }
    }
}

※ 내부 클래스에서 private 멤버를 이용할 수 있다.

  • private는 원래 다른 클래스에서는 사용할 수 없다.
  • static 클래스 내에서는 여전히 안된다. instance 멤버이기 때문이다

※ 지역 내부 클래스에서는 변수는 이용할 수 없고 상수(final)만 이용할 수 있다.

  • method() 내부의 변수는 지역변수이므로 method() 종료와 함께 소멸된다. method()는 한번 호출되면 종료와 함께 끝나기 때문이다.
  • 내부 클래스의 객체가 더 오래 존재할 수 있다. 누구보다? 지역변수보다 method()가 종료되어도 상수니까 사용할 수 있다.
  • 하지만 JDK1.8부터는 변수의 값을 설정하고 바꾸지만 않으면 에러가 나지 않는다.그래도 그냥 왠만하면 붙이는 것이 좋다.

외부 클래스와 내부 클래스의 변수 구분하기

class Outer3{        
    int value = 10;        //Outer3.this.value    
        
    class Inner{    
        int value = 20;        //this.value
        
        void method1(){
            int value = 30;        // value
            System.out.println("            value:" + value);
            System.out.println("       this.value:" + this.value);
            System.out.println("Outer3.this.value:" + Outer3.this.value);
        }
    }    
}        
        
class Ex7_16{        
    public static void main(String args[]){    
        Outer3 outer = new Outer3();
        Outer3.Inner inner = outer.new Inner();
        inner.method1();
    }
}

[참고 자료]

[자바의 정석 - 기초편] ch7-42~44 내부클래스의 종류, 특징, 선언

[자바의 정석 - 기초편] ch7-45~50 내부클래스의 제어자와 접근성

반응형

+ Recent posts