동기화된 컬렉션


컬렉션 프레임워크의 대부분의 클래스들은 싱글 스레드 환경에서 사용할 수 있도록 설계되어있음

그렇기에 여러 스레드가 동시에 컬렉션에 접근한다면 의도하지 않게 데이터가 변경될 수 있는

불안정한 상태가 된다.



synchronizeList(List<T> list) - list를 동기화된 list로 리턴

synchronizeMap(Map<K, V> map) - map을 동기화된 map으로 리턴

synchronizeSet(Set<T> set) - set을 동기화된 set으로 리턴


ArrayList, HashSet, HashMap이 대표적으로 싱글스레드 기반으로 설계된 컬렉션 클래스인데,

이를 멀티 스레드 환경에서 쓸 수 있도록 컬렉션 프레임워크는 비동기화된 메소드를 동기화된

메소드로 래핑하는 synchronizeXXX( ) 메소를 제공한다.



예제코드


1
2
// 리스트를 동기화된 리스트로 변환
List<T> list = Collections.synchronizedList(new ArrayList<T>());
cs


1
2
// map를 동기화된 map으로 변환
Map<K,V> map = Collections.synchronizedMap(new HashMap<K,V>());
cs


1
2
// set를 동기화된 set으로 변환
Set<T> set = Collections.synchronizedSet(new HashSet<T>());
cs


람다식 메소드 참조


메소드를 참조해서 매개 변수의 정보 및 리턴 타입을 알아내어,

람다식에서 불필요한 매개변수는 제거하는 것



사용법 예시)

두수를 입력받아 큰 값을 리턴하는 Math 클래스의 max메소드


1
2
3
4
5
6
7
8
//Math클래스의 max() 참조 방법
 
//람다식은 단순히 두 개의 값을 max메소드에 전달하는 역활만 함.
(x, y) -> Math.max(x, y)
 
 
//메소드 참조를 이용한 람다식 표현
Math :: max
cs



예제코드


1
2
3
4
5
6
7
8
9
10
11
12
public class Calculator {
    //정적 메소드
    public static int staticMethod(int x, int y) {
        return x + y;
    }
 
    //인스턴스 메소드    
    public int instanceMethod(int x, int y) {
        return x + y;
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MethodReferencesExample {
    public static void main(String[] args) {
        IntBinaryOperator operator;
        
        //정적 메소드 참조
        operator = (x,y) -> Calculator.staticMethod(x, y);
        System.out.println("결과 1 : " + operator.applyAsInt(1,2));
        
        operator = Calculator :: staticMethod;
        System.out.println("결과 2 : " + operator.applyAsInt(3,4));
 
        //정적 메서드는 '클래스명 :: 정적메서드' 형태로 참조 가능
        
        //인스턴스 메서드 참조
        Calculator obj = new Calculator();
        operator = (x,y) -> obj.instanceMethod(x, y);
        System.out.println("결과 3 : " + operator.applyAsInt(5,6));
        
        operator = obj :: instanceMethod;
        System.out.println("결과 3 : " + operator.applyAsInt(7,8));
    }
}
cs




람다식 생성자 참조


생성자 참조도 같은 방법으로 가능하다.



예제코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.function.BiFunction;
import java.util.function.Function;
 
public class ConstructorReferenceExample {
    
    /*
     * 람다식에서의 생성자 참조 "클래스명 :: new"
     */
    
    public static void main(String[] args) {
        Function<String, Member> function1 = Member :: new;
        //매개변수 1개
        Member member1 = function1.apply("dong1");
        
        BiFunction<StringString, Member> function2 = Member :: new;
        //매개변수 2개
        Member member2 = function2.apply("길동""dong1");
    }
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Member {
    private String name;
    private String id;
    
    public Member() {
        System.out.println("기본 생성자");
    }
    
    public Member(String id) {//매개변수 1개
        System.out.println("Member(String id) 실행");
        this.id = id;
    }
    
    public Member(String name, String id) { //매개변수 2개
        System.out.println("Member(String name, String id) 실행");
        this.name = name;
        this.id = id;
    }
}
cs


제너릭 타입도 다른 타입과 마찬가지로 부모클래스가 될 수 있다.


특징

자식 제너릭타입에 타입 파라미터를 추가 가능!



Product라는 제너릭타입이 있다.


1
2
3
public class Product<T, M> {
    //생략
}
cs



Product를 상속받은 ChildProduct는 추가로 타입파라미터를 가질수 있다.

1
2
3
4
public class ChildProduct<T, M, C> extends Product<T, M> {
            //제너릭 타입을 상속받을 때 자식은 추가 타입 파라미터를 가질수 있다.
    //생략..
}
cs


제너릭 사용 시 장점


1. 컴파일시 강한 타입체크

2. 타입변환을 제거



장점을 제너릭을 사용하지 않을 때와 제너릭을 사용했을 때

코드가 어떻게 달라지는지 직접 보면서 살펴보자.



제너릭을 사용하지 않고 클래스 정의


1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
public class NoGenericBox {
    
    /*
     * 제너릭을 사용하지 않은 클래스
     * Object는 최상위 클래스로 어떤 타입이라도 담을 수 있다.
     * 하지만 다른 타입의 변수에 담을려면 타입변환이 필요하다.
     */
    
    private Object object;
    public void set(Object object) { this.object = object; }
    public Object get() { return object; }
}
 
cs



제너릭을 사용하지 않은 객체에 String을 넣고 빼보기


1
2
3
4
5
6
7
8
9
10
11
12
public class NoGenericExample {
    public static void main(String[] args) {
        NoGenericBox box = new NoGenericBox();
        
        box.set("배"); 
        //object에 '배'가 담김 --> Object타입
        
        String fruit = (String)box.get(); 
        //'배'를 String으로 형변환이 필요
    }
}
 
cs



제너릭을 사용한 클래스 정의


1
2
3
4
5
6
7
8
9
10
11
public class GenericBox<T> {
    
    /*
     * 제너릭을 이용한 클래스 정의
     * 제너릭타입 T를 클래스 생성시 파라미터로 전달하여 형변환이 필요없다.
     */
    
    private T t;
    public T get() { return t; }
    public void set(T t) { this.t = t; }
}
cs




제너릭을 사용한 객체에 String 넣고 빼기


1
2
3
4
5
6
7
8
9
10
11
12
public class GenericBoxExample {
    public static void main(String[] args) {
        GenericBox<String> box1 = new GenericBox<String>();
        //제너릭을 이용한 객체 생성
        box1.set("수박");
        String fruit = box1.get();//제너릭으로 타입을 제한했기데 형변환이 필요없다.
        
        GenericBox<Integer> box2 = new GenericBox<Integer>();
        box2.set(5);
        int count = box2.get();
    }
}
cs


'Java' 카테고리의 다른 글

[제너릭]와일드카드 타입  (0) 2017.02.17
[제너릭]제너릭 메소드  (0) 2017.02.16
Thread 상속으로 thread 생성  (0) 2017.01.27
Runnable을 이용한 Thread 생성 방법들  (0) 2017.01.25
멀티 스레드 개념  (0) 2017.01.25

filter와 interceptor의 차이


둘의 기본적인 차이점은 호출되는 시점이 다르다는 것이다.


호출되는 시점이 어떻게 다른지 그림을 보면 더욱 이해가 쉽다.





그림을 보면 

filter는 dispatcherServlet가 실행되기 전에 실행되도

interceptor는  dispatcherServlet이 실행된 후 controller 실행 전에 실행되는 것을 알 수 있다.



또한 method가 다르다.


Interceptor


preHandle() : 컨트롤러로 들어가기 전
postHanle() : 컨트롤러에 들어갔다 나온후 뷰로 보내기전
afterCompletion() : 뷰까지 끝난 후



Filter 


init() : 필터 인스턴스 초기화

   doFilter() : 전/후 처리
   destroy() : 필터 인스턴스 종료



참고 : http://changpd.blogspot.kr/2013/03/spring.html

문제



풀이 


_M#]



배열이란?


여러 데이터를 하나의 이름으로 그룹핑하여 관리하기 위한 자료구조


거의 모든 언어에 포함



배열의 구성

    public class ArrayTest {
         int[] numbers1 = new int[4];
       // int[]에서 
       // int는 엘리먼트의 데이터 타입, []은 배열을 의미
       // new int[4]에서
       // new는 생성자, [4]는 배열의 크기
    }
    

배열은 엘리먼트로 구성되어 있고,

엘리먼트는 index와 value로 구성되어 있다.


 학생1

학생2 

학생3 

학생4 

 0


여기서 학생1이 value이고 0은 index

학생1과 0을 묶어서 엘리먼트 하나를 이룬다.


배열의 생성

    public class ArrayTest {
         int[] numbers1 = new int[4];
         int[] numbers2 = {10, 20, 30, 40};
         int[] numbers3 = new int[] {10, 20, 30, 40};
    }
    

배열에 들어갈 값을 미리 알고 있을 경우, 생성과 초기화를 한번에 할 수 있다.



배열의 조회

    public class ArrayTest {    
        public static void main(String[] args) {
                 int[] numbers1 = new int[4];
                 int[] numbers2 = {10, 20, 30, 40};
                 int[] numbers3 = new int[] {10, 20, 30, 40};
          
                 // 나중에 배열 초기화 방법
                numbers1[0] = 10;
                numbers1[1] = 20;
		
                //배열의 값조회(인덱스를 이용)
                System.out.println(numbers1[0]); //  10이 출력
                
               //배열의 길이
               System.out.println(numbers1.length);  // 4가 출력(처음 만들때 4개의 방을 만들었음)
	}     
    }



배열과 반복문 (배열 사용법!!)

  
               //배열의 길이
               System.out.println(numbers1.length);  // 4가 출력(처음 만들때 4개의 방을 만들었음)

               for(int i=0; i


배열의 단점과 장점


단점 : 배열의 크기가 조정이 불가능, 처음 생성할 때 크기로 고정

        별다른 기능(메서드)가 없다.


장점 : 크기가 고정되어있고, 별다른 기능이 없기 때문에 작고 가볍고 단순하다.

         이는 다른 곳의 부품이 되기 쉽다는 의미, 배열의 확장성이 강하다!! 다른 자료구조나 활용도 면에서...



참고: https://opentutorials.org/module/1335/8738

'자료구조' 카테고리의 다른 글

[Map] HashMap  (0) 2017.03.10
[Set]HashSet의 특징  (1) 2017.03.09
[그래프]넓이 우선 탐색(BFS)  (0) 2017.03.07
[그래프] 인접리스트와 인접행렬을 이용한 구현  (0) 2017.02.26
ArrayList와 LinkedList  (0) 2017.01.02

+ Recent posts