Java 유틸리티클래스 라이브러리는 다양한 특정 문제를 해결하는 데 도움이 되는 상당히 완전한 컨테이너 세트를 제공합니다. 저는 Android 개발자이고 저를 포함한 많은 Android 개발자가 ListView(RecycleView) + BaseAdapter + ArrayList의 삼총사에 가장 능숙하기 때문에 제가 주로 사용하는 유일한 컨테이너는 ArrayList와 HashMap입니다. 결과적으로 Java 컨테이너 시스템 전체에 대한 이해와 활용은 아직 매우 얕은 수준에 머물러 있습니다. 자신을 아끼고 개선에 대해 생각하고 싶지 않다면 나를 따라 Java 컨테이너에 대한 관련 지식을 요약하십시오.
상속Java 컨테이너 클래스의 구조
상세 소개
목록
설정
대기열
반복 기기
컬렉션
지도
제안
고급 · 동시 컨테이너
CopyOnWriteArrayList 및 Copy-On-Write 전략
ConcurrentLinkedQueue
ConcurrentHashMap 및 잠금 분할 기술
블로킹 큐
Java 컨테이너 클래스 라이브러리는 Collection과 Map이라는 서로 다른 개념을 가진 두 개의 컨테이너를 정의합니다
Collection 일련의 독립적인 요소로, 이러한 요소는 Obey 하나 또는 더 많은 규칙. 목록은 삽입 순서대로 요소를 보유해야 합니다. 세트에는 중복된 요소가 있을 수 없습니다. 대기열은 대기열 규칙에 따라 객체 가 생성되는 순서를 결정합니다.
(기사에 나온 Jdk 소스 코드 버전은 특별한 지침이 없는 jdk1.8.0_101입니다.)
public interface Collection<E> extends Iterable<E> { int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator(); Object[] toArray(); <T> T[] toArray(T[] a); boolean add(E e); boolean remove(Object o); boolean containsAll(java.util.Collection<?> c); boolean addAll(java.util.Collection<? extends E> c); boolean removeAll(java.util.Collection<?> c); ... //省略了其他方法 }
보시다시피 java는 Collection 인터페이스와 기본 인터페이스를 정의합니다. 내부 컬렉션의 작업 방법, 컬렉션은 기본적으로 컬렉션의 끝에 요소를 추가하고 지정된 요소를 삭제하는 등의 작업을 수행할 수 있습니다. List, Set 및 Queue 인터페이스는 모두 Collection에서 상속되며 다양한 메서드를 정의합니다.
Map 키를 사용하여 값을 조회할 수 있는 "키-값" 개체 집합입니다.
public interface Map<K,V> { int size(); boolean containsKey(Object key); boolean containsValue(Object value); V get(Object key); V put(K key, V value); V remove(Object key); void putAll(java.util.Map<? extends K, ? extends V> m); void clear(); Set<K> keySet(); Collection<V> values(); Set<java.util.Map.Entry<K, V>> entrySet(); interface Entry<K,V> { K getKey(); V getValue(); V setValue(V value); boolean equals(Object o); int hashCode(); ... } boolean equals(Object o); int hashCode(); }
Map 내부 인터페이스 Entryb77a8d9c3c319e50d4b02a976b347910는 Map의 키-값 쌍에 해당합니다.
먼저 Iterator를 소개하겠습니다. 반복자 자체도 디자인 패턴 입니다. 디자인의 원래 의도는 다양한 종류의 컨테이너 구현이 있다는 것이며, 컨테이너를 순회하려면 신경쓰지 말아야 합니다. 먼저 컨테이너 구현에 대해 자세히 설명하고, 두 번째로 순회 작업이 가벼워야 합니다. 반복자는 컨테이너에 대한 액세스를 통합하고 생성 비용이 저렴합니다. 반복자는 한 방향으로만 이동할 수 있다는 점은 주목할 가치가 있습니다.
public interface Iterator<E> { boolean hasNext(); E next(); default void remove() { throw new UnsupportedOperationException("remove"); } default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); } }
컨테이너의 iterator() 메소드를 통해 컨테이너의 반복자를 가져옵니다.
반복자의 next()를 사용하여 다음 요소를 가져오고
hasNext()가 있는지 확인합니다. 모든 요소
제거()는 지정된 요소
를 삭제합니다. ListIterator는 Iterator의 확장이며 다양한 List 클래스 액세스에 사용되며 양방향 이동을 지원합니다.
List는 요소를 특정 순서로 유지하도록 보장합니다. List 인터페이스는 Collection을 기반으로 하는 수많은 메서드를 추가하여 삽입 및 제거가 가능하도록 합니다. 강요.
public interface List<E> extends Collection<E> { ... boolean add(E e); boolean remove(Object o); boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean addAll(int index, Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); E get(int index); E set(int index, E element); void add(int index, E element); E remove(int index); int indexOf(Object o); int lastIndexOf(Object o); java.util.List<E> subList(int fromIndex, int toIndex); ... }
List에는 ArrayList와 LinkedList의 두 가지 유형이 있습니다
List 유형 | 장점 | 단점 | 기본 구현 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ArrayList | 요소에 대한 무작위 액세스가 더 빠릅니다 td> | 중간 요소 삽입 및 삭제 속도가 느림 |
배열
|
||||||||||||
LinkedList | 중간 요소 삽입 및 삭제, 순차 액세스 최적화 | 랜덤 액세스 요소가 느림 | 이중 연결 목록 |
Set은 중복된 요소를 저장하지 않으며 일반적으로 요소를 빠르게 찾는 데 사용됩니다. Set은 추가 기능 없이 Collection과 정확히 동일한 인터페이스를 가지고 있다는 점은 언급할 가치가 있습니다. 저장된 요소는 equals() 메소드를 정의해야 합니다
Set类型 | 使用场景 | 底层实现 |
---|---|---|
HashSet | 快速查找,元素必须定义hashCode() | 链表 |
TreeSet | 保持次序,元素必须实现Comparable接口 | 红-黑树结构 |
LinkedHashSet | 维护次序的HashSet, 元素必须定义hashCode() | 链表 |
除了并发应用,Queue仅有的两个实现是LinkedList和PriorityQueue, 其中LinkedList同时实现了List, Deque接口。它们的差异在于排序行为而不是性能。
public interface Queue<E> extends Collection<E> { boolean add(E e); boolean offer(E e); E remove(); E poll(); E element(); E peek(); }
Map类型 | 使用场景 | 底层实现 |
---|---|---|
HashMap | 快速查询 | 散列表 |
LinkedHashMap | 迭代遍历具有顺序(插入顺序 or 最近最少使用) | 链表 |
TreeMap | 具有排序,唯一可以返回子树的Map(subMap()) | 红-黑树结构 |
WeakHashMap | 弱键映射,映射之外无引用的键,可以被垃圾回收 | 散列表 |
ConcurrentHashMap | 线程安全的Map | 链表 |
IdentityHashMap | 使用==代替equals()对键进行排序,专位解决特殊问题 | 链表 |
HashMap을 수동으로 조정하여 용량, 초기 용량, 크기, 로드 비율 등과 같은 개념과 관련된 성능을 조정할 수 있습니다. 관심이 있으시면 관련 정보를 읽어보실 수 있습니다.
벡터 열거형 해시 테이블 스택과 같은 오래된 컨테이너를 사용하지 마십시오(예, 이것은 Java의 원래 나쁜 디자인입니다. 연습, LinkedList 추천)
여기서 자세한 구현에 대해서는 논하지 않고, 관심 있는 분들은 간단히 기본 지식만 소개해주세요. "Java Concurrent 프로그래밍" 아트" 책을 읽을 수 있습니다.
COW라고도 하는 Copy-On-Write는 프로그래밍에 사용되는 최적화 전략입니다. 기본 아이디어는 모든 사람이 처음부터 동일한 콘텐츠를 공유한다는 것입니다. 누군가가 콘텐츠를 수정하려고 하면 실제로 콘텐츠를 복사하여 새로운 콘텐츠를 만든 다음 이를 수정합니다. 이것은 일종의 지연된 게으름 전략입니다. JDK1.5부터 Java 동시성 패키지는 CopyOnWrite 메커니즘을 사용하여 구현된 두 개의 동시 컨테이너(CopyOnWriteArrayList 및 CopyOnWriteArraySet)를 제공합니다. CopyOnWrite 컨테이너는 매우 유용하며 여러 동시 시나리오에서 사용할 수 있습니다.
CopyOnWrite 컨테이너는 쓰기 시 복사되는 컨테이너입니다. 컨테이너에 요소를 추가할 때 현재 컨테이너에 직접 추가하는 것이 아니라 먼저 현재 컨테이너를 복사하여 새 컨테이너를 만든 다음 요소를 추가한 후 새 컨테이너에 요소를 추가한다는 것이 널리 이해되고 있습니다. 그런 다음 원래 컨테이너의 참조가 새 컨테이너를 가리키도록 합니다. 이것의 장점은 현재 컨테이너가 어떤 요소도 추가하지 않기 때문에 잠금 없이 CopyOnWrite 컨테이너에서 동시 읽기를 수행할 수 있다는 것입니다. 따라서 CopyOnWrite 컨테이너도 읽기와 쓰기를 분리한 아이디어이고, 읽기와 쓰기는 다른 컨테이너입니다.
CopyOnWrite 컨테이너는 데이터의 최종 일관성만 보장할 수 있지만 데이터의 실시간 일관성은 보장할 수 없습니다. 따라서 작성된 데이터를 즉시 읽으려면 CopyOnWrite 컨테이너를 사용하지 마십시오.
동시 프로그래밍에서는 스레드로부터 안전한 대기열이나 목록을 사용해야 하는 경우가 있습니다. 스레드 안전성을 달성하는 방법에는 일반적으로 두 가지가 있습니다. 하나는 차단 알고리즘을 사용하는 것이고, 다른 하나는 비차단 알고리즘을 사용하는 것입니다. Non-Blocking 알고리즘 구현의 기본은 루프 CAS(Compare and Swipe 비교 및 교환)입니다.
ConcurrentLinkedQueue의 기술적 구현은 CopyOnWriteArrayList 및 Copy와 유사하지만 전체 컨테이너 대신 컨테이너 콘텐츠의 일부만 복사하고 수정할 수 있습니다. ConcurrentLinkedQueue는 헤드 노드와 테일 노드로 구성됩니다. 각 노드는 노드 요소(항목)와 다음 노드(다음)를 가리키는 참조로 구성됩니다. 노드는 next를 통해 연결되어 연결된 목록 구조의 큐를 형성합니다.
ConcurrentHashMap은 스레드로부터 안전하고 효율적인 HashMap입니다. 멀티 스레드 환경에서 스레드로부터 안전하지 않은 HashMap을 사용하면 무한 루프가 발생하고 기사에서 제안한 대로 HashTable과 같은 오래된 컨테이너는 비효율적입니다. 스레드를 보장하려면 synchr화를 사용하세요. 안전). ConcurrentHashMap은 잠금 분할 기술을 사용하여 동시 사용 효율성을 크게 향상시킵니다.
잠금 분할 기술: 컨테이너에 여러 개의 잠금이 있고 각 잠금이 컨테이너의 데이터 일부를 잠그는 데 사용된다고 가정합니다. 여러 스레드가 컨테이너의 서로 다른 데이터 세그먼트에 액세스하면 다음과 같은 문제가 발생합니다. 스레드 간 잠금이 없습니다. 동시 액세스 효율성을 높이기 위한 경쟁입니다.
JDK7은 7개의 차단 대기열을 제공하며 구현 원칙은 모두 알림 메커니즘을 기다리는 생산-소비 모델을 기반으로 합니다.
차단 대기열 유형 | 기능 |
---|---|
배열 구조로 구성된 제한된 차단 큐 | |
LinkedBlockingQueue | 연결된 목록 구조로 구성된 제한된 차단 큐 |
PriorityBlockingQueue | 우선순위무제한 차단 큐 정렬 |
DelayQueue | 우선순위 큐를 사용하여 구현된 무제한 차단 큐 | SynchronousQueue | 요소를 저장하지 않는 차단 큐 |
LinkedTransferQueue | 연결된 목록 구조로 구성된 무한한 차단 큐 |
LinkedBlockingQueue | 연결된 목록 구조로 구성된 양방향 차단 큐 |
위 내용은 Java 컨테이너 관련 지식의 종합 요약에 대한 자세한 소개(그림)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!