[새싹] 현대IT&E 231024 기록 - JAVA 17-18장

최정윤·2023년 10월 24일
0

새싹

목록 보기
6/67
post-custom-banner

이전 수업 요약 정리

자료형 8가지는 무엇인가요?

string builder와 string buffer의 차이점은 무엇인가요?

가장 큰 차이점은 동기화의 유무로써 StringBuffer는 동기화 키워드를 지원하여 멀티쓰레드 환경에서 안전하다는 점(thread-safe) 입니다. 참고로 String도 불변성을 가지기때문에 마찬가지로 멀티쓰레드 환경에서의 안정성(thread-safe)을 가지고 있습니다.

반대로 StringBuilder는 동기화를 지원하지 않기때문에 멀티쓰레드 환경에서 사용하는 것은 적합하지 않지만 동기화를 고려하지 않는 만큼 단일쓰레드에서의 성능은 StringBuffer 보다 뛰어납니다.

코어 갯수와 쓰레드 갯수의 관계성을 생각해보자.

17장. 컬렉션 프레임워크

  • 컬렉션은 여러 데이터를 수집해 놓은 자료구조를 말한다.
  • 컬렉션의 가장 큰 특징은 데이터 저장 공간의 크기가 동적으로 변화한다는 것이다.
    • 데이터 개수가 시간적으로 변할 때 컬렉션 프레임워크가 유용하다.

17.1 컬렉션 프레임워크의 개념과 구조

17.1.1 컬렉션이란?

  • 컬렉션은 동일한 타입을 묶어 관리하는 자료구조를 말한다.
  • 배열은 동일한 타입을 묶어 관리하는 것이지만, 배열을 컬렉션이라 부르지 않는다.
  • 배열과 컬렉션은 무엇이 다를까?
    • 컬렉션과 배열이 구분되는 가장 큰 특징은 데이터의 저장 용량을 동적으로 관리 할 수 있다는 것이다.
    • 배열은 생성 시점에 저장 공간의 크기를 확정해야 하고, 나중에 변경할 수 있는 반면, 컬렉션의 저장 공간은 데이터의 개수에 따라 얼마든지 동적으로 변화할 수 있다.
      -컬렉션은 메모리 공간이 허용하는 한 저장 데이터의 개수에 제약이 없다.

17.1.2 컬렉션 프레임워크란?

  • 라이브러리: 단순히 연관된 클래스와 인터페이스들의 묶음
  • 프레임워크: 클래스 또는 인터페이스를 생성하는 과정에서 설계의 원칙 또는 구조에 따라 클래스 또는 인터페이스를 설계하고, 설계된 클래스와 인터페이스를 묶어 놓은 개념이다.
  • 컬렉션 프레임워크: 컬렉션 + 프레임워크 / 리스트, 스택, 큐, 트리 등의 자료구조에 정렬, 탐색 등의 알고리즘을 구조화해 놓은 프레임워크다.

17.2 List < E > 컬렉션 이터페이스

17.2.1 배열과 리스트의 차이점

  • 배열과 리스트의 가장 큰 차이점은 저장 공간의 크기가 고정적이냐, 동적으로 변화하느냐이다.

17.2.2 List < E > 객체 생성하기

  • List < E >는 인터페이스이기 때문에 객체를 스스로 생성할 수 없다.
    • 객체를 생성하기 위해서는 List < E >를 상속받아 자식 클래스를 생헝하고, 생성한 자식 클래스를 이용해 객체를 생성해야 한다.
  • 하지만 컬렉션 프레임워크를 이용할 때는 직접 인터페이스를 구현하지 않아도 된다.
    • 컬렉션 프레임워크 안에 이미 각각의 특성 및 목적에 따른 클래스가 구현돼 있기 때문이다.

CreateListObject.java

package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

public class CreateListObject {
	public static void main(String[] args) {
		// 1. List 구현 클래스의 생성자를 사용해 객체 생성
		List<Integer> aList1 = new ArrayList<>();		// capacity = 10
		List<Integer> aList2 = new ArrayList<>(30);		// capacity = 30
		List<Integer> aList3 = new Vector<>();			// capacity = 10
		List<Integer> aList4 = new Vector<>(20);		// capacity = 20
		List<Integer> aList5 = new LinkedList<>();		// capacity = 10
//		List<Integer> aList6 = new LinkedList<>(30);	// 저장 용량 지정 불가

		
		// 2. Arrays 클래스의 정적 메서드 활용
		List<Integer> aList7 = new Arrays.asList(1, 2, 3, 4);
		List<String> aList8 = new Arrays.asList("안녕", "방가");
		aList7.set(1, 7);
		aList8.set(0, "감사");
//		aList7.add(5);
//		aList8.remove(0);	// 불가능
		System.out.println(aList7);
		System.out.println(aList8);
	}

}

17.2.4 ArrayList < E > 구현 클래스

ArrayListMethod.java

package collection;

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

public class ArrayListMethod {
	public static void main(String[] args) {
		List<Integer> aList1 = new ArrayList<Integer>();
		aList1.add(3);
		aList1.add(4);
		aList1.add(5);
		System.out.println(aList1.toString());
		
		aList1.add(1, 6);
		System.out.println(aList1.toString());
		
		List<Integer> aList2 = new ArrayList<>();
		aList2.add(1);
		aList2.add(2);
		aList2.addAll(aList1);
		System.out.println(aList2);
		
		List<Integer> aList3 = new ArrayList<>();
		aList3.add(1);
		aList3.add(2);
		aList3.addAll(1, aList3);
		System.out.println(aList3);
		
		aList3.set(1, 5);
		aList3.set(3, 6);
		
		System.out.println(aList3);
		
		aList3.remove(1);
		System.out.println(aList3);
		
		aList3.remove(new Integer(2));
		System.out.println(aList3);
		
		aList3.clear();
		System.out.println(aList3);
		
		System.out.println(aList3.isEmpty());
		
		System.out.println(aList3.size());
		aList3.add(1);
		aList3.add(2);
		aList3.add(3);
		System.out.println(aList3);
		System.out.println(aList3.size());

		System.out.println("0번째: " + aList3.get(0));
		System.out.println("0번째: " + aList3.get(1));
		System.out.println("0번째: " + aList3.get(2));
	
		for(int i = 0; i < aList3.size(); i++)
			System.out.println(i + "번째: " + aList3.get(i));
		
		Object[] object = aList3.toArray();
		System.out.println(Arrays.toString(object));
		
		Integer[] integer1 = aList3.toArray(new Integer[0]);
		System.out.println(Arrays.toString(integer1));
		
		Integer[] integer2 = aList3.toArray(new Integer[5]);
		System.out.println(Arrays.toString(integer2));
	}

}

17.2.7 ArrayList< E >와 LinkedList< E >의 성능 비교

  • ArrayList< E > 객체에서 데이터를 추가하고자 할때 변경 인덱스 이후의 모든 데이터는 한 칸씩 뒤로 밀려나게 되는데, 이는 밀려나는 모든 데이터의 위치 정보를 수정해야 한다는 것을 의미한다.
  • LinkedList< E >는 각 원소의 앞뒤 객체 정보만을 저장하고 있으므로 어딘가에 값이 추가되면 값이 추가된 위치의 앞뒤 데이터 정보만 수정하면된다.
    -> 데이터 추가 삭제 과정에서 속도 차이가 발생한다.

ArrayListVsLinkedList.java

package collection;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ArrayListVsLinkedList {
	public static void main(String[] args) {
		List<Integer> aList = new ArrayList<>();
		List<Integer> linkedList = new LinkedList<>();
		long startTime = 0, endTime = 0;
		
		startTime = System.nanoTime();
		for(int i = 0; i < 100000; i++) {
			aList.add(0, i);
		}
		endTime = System.nanoTime();
		System.out.println("ArrayList 데이터 추가 시간 = " + (endTime-startTime) + " ns");
		startTime = System.nanoTime();
		for(int i = 0; i < 100000; i++) {
			linkedList.add(0, i);
		}
		endTime = System.nanoTime();
		System.out.println("LinkedList 데이터 추가 시간 = " + (endTime-startTime) + " ns");
		
		startTime = System.nanoTime();
		System.out.println("ArrayList 데이터 검색 시간 = " + (endTime-startTime) + " ns");
		
		startTime = System.nanoTime();
		for(int i = 0; i < 100000; i++) {
			aList.remove(0);
		}
		endTime = System.nanoTime();
		System.out.println("ArrayList 데이터 제거 시간 = " + (endTime-startTime) + " ns");
		
		startTime = System.nanoTime();
		for(int i = 0; i < 100000; i++) {
			linkedList.remove(0);
		}
		endTime = System.nanoTime();
		System.out.println("LinkedList 데이터 제거 시간 = " + (endTime-startTime) + " ns");
	}

}

17.3 Set< E > 컬렉션 인터페이스

17.3.3 HashSet< E > 구현 클래스

HashSetMethod.java

package collection;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetMethod {
	public static void main(String[] args) {
		Set<String> hSet1 = new HashSet<>();
		hSet1.add("가");
		hSet1.add("나");
		hSet1.add("다");
		System.out.println(hSet1.toString());
		
		Set<String> hSet2 = new HashSet<>();
		hSet2.add("나");
		hSet2.add("다");
		hSet2.addAll(hSet1);
		System.out.println(hSet2.toString());
		
		hSet2.remove("나");
		System.out.println(hSet2.toString());
		
		hSet2.clear();
		System.out.println(hSet2.toString());
		
		System.out.println(hSet2.isEmpty());
		
		Set<String> hSet3 = new HashSet<>();
		hSet3.add("가");
		hSet3.add("나");
		hSet3.add("다");
		System.out.println(hSet3.contains("나"));
		System.out.println(hSet3.contains("라"));
		
		System.out.println(hSet3.size());
		
		Iterator<String> iterator = hSet3.iterator();
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		
		Object[] objArray = hSet3.toArray();
		System.out.println(Arrays.toString(objArray));
		
		String[] strArray1 = hSet3.toArray(new String[0]);
		System.out.println(Arrays.toString(strArray1));
		
		
		String[] strArray2 = hSet3.toArray(new String[5]);
		System.out.println(Arrays.toString(strArray2));
	}
}

17.3.4 LinkedHashSet< E > 구현 클래스

LinkedHashSetMethod.java

package collection;

import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetMethod {

	public static void main(String[] args) {
		Set<String> linkedSet1 = new LinkedHashSet<>();
		linkedSet1.add("가");
		linkedSet1.add("나");
		linkedSet1.add("다");
		System.out.println(linkedSet1.toString());
		
		Set<String> linkedSet2 = new LinkedHashSet<>();
		linkedSet2.add("나");
		linkedSet2.add("다");
		linkedSet2.addAll(linkedSet1);
		System.out.println(linkedSet2.toString());
		
		linkedSet2.remove("나");
		System.out.println(linkedSet2.toString());
		
		linkedSet2.clear();
		System.out.println(linkedSet2.toString());
		
		System.out.println(linkedSet2.isEmpty());
		
		Set<String> linkedSet3 = new LinkedHashSet<>();
		linkedSet3.add("가");
		linkedSet3.add("나");
		linkedSet3.add("다");
		System.out.println(linkedSet3.contains("나"));
		System.out.println(linkedSet3.contains("라"));
		
		System.out.println(linkedSet3.size());
		
		Iterator<String> iterator = linkedSet3.iterator();
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		Object[] objArray = linkedSet3.toArray();
		System.out.println(Arrays.toString(objArray));
		
		String[] strArray1 = linkedSet3.toArray(new String[0]);
		System.out.println(Arrays.toString(strArray1));
		
		String[] strArray2 = linkedSet3.toArray(new String[5]);
		System.out.println(Arrays.toString(strArray2));
	}

}

17.3.5 TreeSet< E > 구현 클래스

TreeSetMethod_1.java

package collection;

import java.util.Comparator;
import java.util.TreeSet;

class MyComparableClass implements Comparable<MyComparableClass> {
    int data1;
    int data2;

    public MyComparableClass(int data1, int data2) {
        this.data1 = data1;
        this.data2 = data2;
    }

    @Override
    public int compareTo(MyComparableClass other) {
        if (this.data1 < other.data1) {
            return -1;
        } else if (this.data1 == other.data1) {
            return 0;
        } else {
            return 1;
        }
    }
}

class MyClass {
    int data1;
    int data2;

    public MyClass(int data1, int data2) {
        this.data1 = data1;
        this.data2 = data2;
    }
}

public class TreeSetMethod_2 {
    public static void main(String[] args) {
        TreeSet<Integer> treeSet1 = new TreeSet<Integer>();
        Integer intValue1 = new Integer(20);
        Integer intValue2 = new Integer(10);
        treeSet1.add(intValue1);
        treeSet1.add(intValue2);
        System.out.println(treeSet1.toString());

        TreeSet<String> treeSet2 = new TreeSet<String>();
        String str1 = "가나";
        String str2 = "다라";
        treeSet2.add(str1);
        treeSet2.add(str2);
        System.out.println(treeSet2.toString());

        TreeSet<MyComparableClass> treeSet4 = new TreeSet<MyComparableClass>();
        MyComparableClass myComparableClass1 = new MyComparableClass(2, 5);
        MyComparableClass myComparableClass2 = new MyComparableClass(3, 3);
        treeSet4.add(myComparableClass1);
        treeSet4.add(myComparableClass2);
        for (MyComparableClass mcc : treeSet4) {
            System.out.println(mcc.data1);
        }

        TreeSet<MyClass> treeSet5 = new TreeSet<MyClass>(new Comparator<MyClass>() {
            @Override
            public int compare(MyClass o1, MyClass o2) {
                if (o1.data1 < o2.data1) return -1;
                else if (o1.data1 == o2.data1) return 0;
                else return 1;
            }
        });
        MyClass myClass1 = new MyClass(2, 5);
        MyClass myClass2 = new MyClass(3, 3);
        treeSet5.add(myClass1);
        treeSet5.add(myClass2);
        for (MyClass mcc : treeSet5) {
            System.out.println(mcc.data1);
        }
    }
}

17.4 Map< K, V > 컬렉션 인터페이스

17.4.3 HashMap< K, V >

HashMapMachanism.java

package collection;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

class A {
    int data;

    public A(int data) {
        this.data = data;
    }

    @Override
    public int hashCode() {
        return Objects.hash(data);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof A) {
            A other = (A) obj;
            return this.data == other.data;
        }
        return false;
    }
}

class B {
    int data;

    public B(int data) {
        this.data = data;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof B) {
            B other = (B) obj;
            return this.data == other.data;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(data);
    }
}

class C {
    int data;

    public C(int data) {
        this.data = data;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof C) {
            C other = (C) obj;
            return this.data == other.data;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(data);
    }
}

public class HashMapMachanism {
    public static void main(String[] args) {
        Map<A, String> hashMap1 = new HashMap<>();
        A a1 = new A(3);
        A a2 = new A(3);
        System.out.println(a1 == a2);
        System.out.println(a1.equals(a2));
        System.out.println(a1.hashCode() + ", " + a2.hashCode());
        hashMap1.put(a1, "첫 번째");
        hashMap1.put(a2, "두 번째");
        System.out.println("hashMap1.size(): " + hashMap1.size());
        System.out.println();

        Map<B, String> hashMap2 = new HashMap<>();
        B b1 = new B(3);
        B b2 = new B(3);
        System.out.println(b1 == b2);
        System.out.println(b1.equals(b2));
        System.out.println(b1.hashCode() + ", " + b2.hashCode());
        hashMap2.put(b1, "첫 번째");
        hashMap2.put(b2, "두 번째");
        System.out.println("hashMap2.size(): " + hashMap2.size());
        System.out.println();

        Map<C, String> hashMap3 = new HashMap<>();
        C c1 = new C(3);
        C c2 = new C(3);
        System.out.println(c1 == c2);
        System.out.println(c1.equals(c2));
        System.out.println(c1.hashCode() + ", " + c2.hashCode());
        hashMap3.put(c1, "첫 번째");
        hashMap3.put(c2, "두 번째");
        System.out.println("hashMap3.size(): " + hashMap3.size());
    }
}

17.4.5 LinkedHashMap< K, V >

TreeMapMethod_1.java

package collection;

import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.SortedMap;
import java.util.TreeMap;

public class TreeMapMethod_1 {
	public static void main(String[] args) {
		TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
		for(int i = 20; i > 9; i -= 2) {
			treeMap.put(i, i+"번째 데이터");
		}
		System.out.println(treeMap.toString());
		
		System.out.println(treeMap.firstKey());
		
		System.out.println(treeMap.firstEntry());
		
		System.out.println(treeMap.lastKey());
		
		System.out.println(treeMap.lastEntry());
		
		System.out.println(treeMap.lowerKey(11));
		System.out.println(treeMap.lowerKey(10));
		
		System.out.println(treeMap.higherKey(11));
		System.out.println(treeMap.higherKey(10));
		
		System.out.println(treeMap.pollFirstEntry());
		System.out.println(treeMap.toString());
		
		System.out.println(treeMap.pollLastEntry());
		System.out.println(treeMap.toString());

		SortedMap<Integer, String> sortedMap = treeMap.headMap(8);
		System.out.println(sortedMap);
		
		NavigableMap<Integer, String> navigableMap = treeMap.headMap(8, true);
		System.out.println(navigableMap);
		
		sortedMap = treeMap.tailMap(14);
		System.out.println(sortedMap);
		
		navigableMap = treeMap.tailMap(14, false);
		System.out.println(navigableMap);
		
		sortedMap = treeMap.subMap(6, 10);
		System.out.println(sortedMap);
		
		navigableMap = treeMap.subMap(6,  false, 10, true);
		System.out.println(navigableMap);
		
		NavigableSet<Integer> navigableSet = treeMap.descendingKeySet();
		System.out.println(navigableSet.toString());
		System.out.println(navigableSet.descendingSet());
		
		navigableMap = treeMap.descendingMap();
		System.out.println(navigableMap.toString());
		System.out.println(navigableMap.descendingMap());
	}

}

17.5 Stack < E > 컬렉션 클래스

17.5.1 Stack< E > 컬렉션의 특징

17.6 Queue < E > 컬렉션 클래스

QueueMethod.java

package collection;

import java.util.LinkedList;
import java.util.Queue;

public class QueueMethod {
	public static void main(String[] args) {
		Queue<Integer> queue1 = new LinkedList<Integer>();
		
		queue1.add(3);
		queue1.add(3);
		queue1.add(3);
		
		System.out.println(queue1.element());
		
		System.out.println(queue1.remove());
		System.out.println(queue1.remove());
		System.out.println(queue1.remove());
		
		System.out.println();
		
		Queue<Integer> queue2 = new LinkedList<Integer>();
		System.out.println(queue1.peek());
		
		queue2.offer(3);
		queue2.offer(4);
		queue2.offer(5);
		
		System.out.println(queue2.peek());

		System.out.println(queue2.poll());
		System.out.println(queue2.poll());
		System.out.println(queue2.poll());
		System.out.println(queue2.poll());
	}

}

18장. 람다식

  • 람다식: 객체 지향형 언어인 자바에서 함수형 프로그래밍 방식을 쓸 수 있게 해 주는 문법 요소이다.

18.1 람다식

  • 람다식은 함수형 프로그래밍 기법을 지원하는 자바의 문법 요소이다.
  • 독립적으로 정의한 함수를 호출만 하면 공통 기능을 사용할 수 있으므로 훨씬 효율적일 것이다.
  • 자바는 객체 지향 언어이므로 모든 함수는 클래스 또는 인터페이스 내부에만 존재한다.

18.2 람다식의 활용

18.2.1 구현 메서드의 약식 표현

FunctionToLambdaExpression.java

package collection;

interface AA {
	void method1();
}

interface BB {
	void method2(int a);
}

interface CC {
	int method3();
}

interface DD {
	double method4(int a, double b);
}

public class FunctionToLambdaExpression {
	public static void main(String[] args) {
		AA a1 = new AA() {
			@Override
			public void method1() {
				System.out.println("입력 x 리턴 x 함수");
			}
		};
		
		AA a2 = () -> {System.out.println("입력 x 리턴 x 함수");};
		AA a3 = () -> System.out.println("입력 x 리턴 x 함수");
		
		BB b1 = new BB() {
			@Override
			public void method2(int a) {
				System.out.println("입력 O 리턴 x 함수");
			}
		};
		BB b2 = (int a) -> {System.out.println("입력 O 리턴 x 함수");};
		BB b3 = (a) -> {System.out.println("입력 O 리턴 x 함수");};
		BB b4 = (a) -> System.out.println("입력 O 리턴 x 함수");
		BB b5 = a -> System.out.println("입력 O 리턴 x 함수");
		
		CC c1 = new CC() {
			@Override
			public int method3() {
				return 4;
			}
		};
		
		CC c2 = () -> {return 4;};
		CC c3 = () -> 4;
		
		DD d1 = new DD() {
			@Override
			public double method4(int a, double b) {
				return a + b;
			}
		};
		
		DD d2 = (int a, double b) -> {return a + b;};
		DD d3 = (a, b) -> {return a + b;};
		DD d4 = (a, b)-> a + b;
	}

}

18.2.2 메서드 참조

RefOfIntanceMethod_Type1_1.java

package collection;

interface AAAA {
	void abc();
}
class BBBB {
	void bcd() {
		System.out.println("메서드");
	}
}

public class RefOfIntanceMethod_Type1_1 {
	public static void main(String[] args) {
		AAAA a1 = new AAAA() {
			@Override
			public void abc() {
				BBBB b = new BBBB();
				b.bcd();
			}
		};
		
		AAAA a2 = () -> {
			BBBB b = new BBBB();
			b.bcd();
		};
		
		BBBB b = new BBBB();
		AAAA a3 = b::bcd;
		a1.abc();
		a2.abc();
		a3.abc();
	}

}

RefOfStaticMethod.java

package collection;

interface AAAAA {
	void abc();
}

class BBBBB {
	static void bcd() {
		System.out.println("메서드");
	}
}

public class RefOfStaticMethod {
	public static void main(String[] args) {
		AAAAA a1 = new AAAAA() {
			@Override
			public void abc() {
				BBBBB.bcd();
			}
		};
		
		AAAAA a2 = () -> {BBBBB.bcd();};
		AAAAA a3 = BBBBB::bcd;
		a1.abc();
		a2.abc();
		a3.abc();
	}
}

[참고자료]

profile
개발 기록장
post-custom-banner

0개의 댓글