자바 기본 16 개 컬렉션 (ArrayList, LinkedList, HashSet, HashMap)

프로그래밍을 좋아하는 당신처럼!
SpringBoot 실습 과정 배우기 https://edu.csdn.net/course/detail/31433
SpringCloud 입문 과정 배우기 https://edu.csdn.net/course/detail/31451


머리말

많은 데이터를 저장했을 때 먼저 어레이를 생각했습니다. 하지만 배열의 길이는 고정되어있어 일정량의 데이터를 저장하면 문제가 발생합니다.
이 기사에서는 Java 컬렉션 프레임 워크의 아키텍처를 이해하고 List, Set 및 Map 인터페이스의 차이점을 파악하고 ArrayList, LinkedList, HashSet 및 HashMap의 사용, 데이터 구조 및 구현 원칙에 중점을 둡니다.

집단 프레임 워크 시스템

여기에 사진 설명 삽입

인터페이스 기능 :

  • 컬렉션 인터페이스
    는 컬렉션의 추가, 삭제, 컬렉션 수와 같은 컬렉션의 일반 메서드를 정의합니다.
  • 목록 인터페이스
    정렬 및 중복 데이터 추가 가능
  • 설정된 인터페이스
    는 별도로 액세스 할 수 없으며 데이터를 반복 할 수 없습니다.

  • 키를 통해 액세스되는 인터페이스 키-값 쌍 매핑

Collection 인터페이스의 주요 방법 :

방법 소개
부울 add (Object obj) 개체 추가
boolean addAll (컬렉션 c) 다른 컬렉션의 모든 개체 추가
부울 제거 (Object obj) 개체 삭제
boolean removeAll (컬렉션 c) 컬렉션의 모든 개체 삭제
무효 clear () 모든 개체 삭제
int 크기 () 저장된 개체 수
부울 contains (Object obj) 개체가 있는지 확인
Object [] toArray () 컬렉션의 객체를 배열로 반환

목록 인터페이스

아래 첨자로 작업 할 수 있으며 중복 데이터를 추가 할 수 있으며
Main 메서드를 정렬 할 수 있습니다 .

방법 소개
void add (int index, Object obj) 특정 위치에 개체 추가
객체 get (int 인덱스) 특정 위치에있는 개체를 반환
객체 제거 (int index) 특정 위치에서 개체 삭제
객체 세트 (int index, Object obj) 특정 위치에있는 개체 교체
목록 subList (int start, int end) 컬렉션의 일부 차단
int indexOf (객체) 컬렉션에서 개체의 위치를 ​​반환합니다.
부울 contains (Object obj) 개체가 있는지 확인

ArrayList 클래스

ArrayList 클래스는 List 인터페이스의 구현 클래스이며 개발 중에 매우 많이 사용되는 컬렉션입니다.
ArrayList의 데이터 구조는 다음과 같습니다.
1 차원 배열

ArrayList의 장단점 :

  • 장점 : 빠른 액세스 속도, 지속적인 저장 공간, 아래 첨자를 통한 직접 위치 지정
  • 단점 : 삭제 및 삽입 성능 저하, 많은 데이터를 앞뒤로 이동해야 함

생성 방법 :

ArrayList arrayList = new ArrayList();

또는

ArrayList arrayList = new ArrayList(默认容量);

데이터 추가 :

add(Object 数据)				添加数据到末尾,参数是Object类型,可以添加任何类型的数据。
add(int 下标,Object 数据)	在特定位置添加数据
addAll(Collection 集合)		添加一个集合中所有数据

데이터 변경 :

set(int 下标,Object 数据)		修改特定位置上数据

액세스 데이터 :

get(下标)				返回某个下标上的数据

데이터 수 :

int size()				数据个数

데이터 삭제 :

remove(int 下标)			删除特定位置上的数据
clear()					删除所有数据

컬렉션
탐색 : foreach 루프

for(Object obj : list){
	System.out.println("集合中的数据:"+obj);
}

일반 for 루프

int size = list.size();
for(int i = 0;i < size;i++){
	Object obj = list.get(i);
	System.out.println("集合中的数据:"+obj);
}

ArrayList 소스 코드 분석 :
데이터를 저장하는 방법? 객체 유형의 1 차원 배열

transient Object[] elementData;

어레이의 초기 길이는 얼마입니까? 10

private static final int DEFAULT_CAPACITY = 10;

ArrayList는 어떻게 동적으로 확장됩니까? 데이터 수가 원래 용량을 초과하면 용량이 원래 용량의 1.5 배로 확장 된 다음 데이터가 새 어레이로 복사됩니다.

private void grow(int minCapacity) {
     // overflow-conscious code
     int oldCapacity = elementData.length;
     int newCapacity = oldCapacity + (oldCapacity >> 1); //扩容1.5倍
     if (newCapacity - minCapacity < 0)
         newCapacity = minCapacity;
     if (newCapacity - MAX_ARRAY_SIZE > 0)
         newCapacity = hugeCapacity(minCapacity);
     // minCapacity is usually close to size, so this is a win:
     elementData = Arrays.copyOf(elementData, newCapacity); //复制数据到新数组中
}

벡터 컬렉션

Vector 컬렉션은 ArrayList와 유사합니다.

  1. 데이터 구조는 모두 1 차원 배열입니다.
  2. 방법은 똑같습니다

차:

  1. ArrayList는 스레드로부터 안전하지 않고 Vector는 스레드로부터 안전합니다.
  2. ArrayList 성능이 더 높습니다.

일반 컬렉션

다음 코드에 어떤 문제가 있습니까?

List list = new ArrayList();
list.add(100);
list.add("123");
int n = (int)list.get(1); //存在类型转换的错误
String s = (String)list.get(0); //存在类型转换的错误

제네릭이 아닌 컬렉션의 경우 추가되는 데이터의 유형에 제한이 없으며, 유형 변환을 위해 데이터를 꺼내면 유형 비 호환성 문제가있다.

일반 컬렉션을 사용하면이 문제를 해결할 수 있습니다.

생성 방법 :

ArrayList<类型> arrayList = new ArrayList<类型>();

예 :

ArrayList<String> arrayList = new ArrayList<String>();
ArrayList<Integer> arrayList = new ArrayList<Integer>();
后面的类型可以省略
ArrayList<Integer> arrayList = new ArrayList<>(); 

이점:

  1. 한 가지 유형의 데이터 만 추가 할 수 있으며 실수하기 쉽지 않음
  2. 유형 변환 없음, 성능 향상
ArrayList<Person> arrList = new ArrayList<Person>();
arrList.add(new Person("张三",20));
arrList.add(new Person("张大三",21));
arrList.add(new Person("张小三",23));
arrList.add(new Person("张三三",26));
arrList.add(100);  //编译错误,不允许添加其他类型
//读取Person对象
Person person = arrList.get(3);
person.hello();
//删除
arrList.remove(0);
//遍历
for(Person per : arrList){
	per.hello();
}

LinkedList

LinkedList의 데이터 구조는 다음
같습니다. 이중 연결 목록
여기에 사진 설명 삽입
여기에 사진 설명 삽입
여기에 사진 설명 삽입

LinkedList의 장단점 :

  • 장점 : 빠른 삭제 및 삽입 속도, 전면 및 후면 지점 수정 만 필요, 데이터 이동 필요 없음
  • 단점 : 액세스 속도가 느리고 앞뒤로 차례대로 이동해야하며 효율성이 낮습니다.

LinkedList 메서드

방법 소개
void addFirst (Object obj) 첫 번째 위치에 개체 추가
void addLast (Object obj) 마지막 위치에 개체 추가
개체 removeFirst () 첫 번째 위치에서 개체 삭제
개체 removeLast () 마지막 위치에서 개체 삭제
객체 getFirst () 첫 번째 위치에서 개체 가져 오기
객체 getLast () 개체의 마지막 위치 가져 오기
void push (Object obj) 스택, 선입 선출, 최종 출력
객체 pop () 스택에서, 선입 선출

LinkedList 소스 코드 탐색

//内部类,保存数据和前后指针
private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;
    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

요소 삽입

//在succ节点前,插入新节点
void linkBefore(E e, Node<E> succ) {
    final Node<E> pred = succ.prev;  	//succ前一个节点
    //创建新节点,prev指向succ前面节点,next指向succ
    final Node<E> newNode = new Node<>(pred, e, succ); 
    succ.prev = newNode;     		//succ的prev指向新节点
    if (pred == null)
        first = newNode;  		 		//前面没有节点,新节点就是首节点
    else
        pred.next = newNode;  		//否则succ前面节点的next指向新节点
    size++;									//数量加1
    modCount++;
}

요소 삽입

//删除x节点
E unlink(Node<E> x) {
     final E element = x.item;
     final Node<E> next = x.next;
     final Node<E> prev = x.prev;
     if (prev == null) {       //x前面节点的next指向x节点的后面节点
         first = next;
     } else {
         prev.next = next;
         x.prev = null;
     }
     if (next == null) {       //x后面节点的prev指向x节点的前面节点
         last = prev;
     } else {
         next.prev = prev;
         x.next = null;
     }
     x.item = null;
     size--;
     modCount++;
     return element;
 }

인터페이스 설정

세트는 중복 데이터를 추가 할 수 없으며 내부 데이터는 별도로 액세스 할 수 없습니다.

일반적으로 사용되는 Set 인터페이스의 구현 클래스는 다음과 같습니다.

  • HashSet 순서없는 세트
  • TreeSet은 자동으로 세트를 정렬합니다.
  • LinkedHashSet는 추가 순서 세트를 유지할 수 있습니다.

HashSet

정렬되지 않은 저장 위치는 해시 알고리즘에 의해 계산됩니다
. 컬렉션에 추가 된 데이터는 hashCode를 구현하고 메소드와 동일해야합니다.
하단 구현은 HashMap이고 데이터는 HashMap의 키에 저장됩니다.

public class HashSet<E> extends AbstractSet<E>
{
   
    private transient HashMap<E,Object> map;
	private static final Object PRESENT = new Object();
    public HashSet() {
        map = new HashMap<>();
    }
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    ...
}

지도 인터페이스

키-값 쌍 구조 액세스 데이터, 찾기 쉽고 효율적입니다.
일반적인 방법 :

방법 소개
V put (K 키, V 값) 지정된 "키-값"쌍을 맵에 저장
V get (객체 키) 지정된 키로 매핑 된 값을 반환합니다.
V 제거 (개체 키) 지정된 키에 따라 맵에서이 "키-값"쌍을 제거하십시오.
부울 containsKey (객체 키) 이 맵에 지정된 키가 있는지 확인
부울 containsValue (객체 값) 이 맵에 지정된 값이 있는지 확인
부울 isEmpty () 이지도에 요소가 있는지 확인
int 크기 () 맵에서 "키-값"쌍의 수를 가져옵니다.
무효 clear () 맵에서 모든 "키-값"쌍을 지 웁니다.
keySet () 설정 이 Map에 포함 된 키 컬렉션을 반환합니다.
컬렉션 값 () 이 맵의 값 모음을 반환합니다.

HashMap

해시 테이블 형식으로 데이터에 액세스하려면 많은 컬렉션을 사용합니다.
생성 방법 :

HashMap<键类型,值类型> hashmap = new HashMap<>();

명령:

//创建HashMap保存人的对象
HashMap<String,Person> map = new HashMap<String,Person>();
Person person1 = new Person("张三",20);
Person person2 = new Person("李四",22);
Person person3 = new Person("王五",20);
//添加人到集合中
map.put(person1.getName(), person1);
map.put(person2.getName(), person2);
map.put(person3.getName(), person3);
//通过键访问值
map.get("张三").hello();
//删除
map.remove("李四");
//添加重复的键,将新的值覆盖原来的值
map.put("李四", new Person("李四",33));
System.out.println("长度:" + map.size());
//遍历所有的键
for(String key : map.keySet()){
	System.out.println("键: " + key);
}
//遍历所有的值
for(Person per : map.values()){
	per.hello();
}
//遍历所有的键和值
for(String key : map.keySet()){
	System.out.println("键: " + key);
	map.get(key).hello();
}

HashMap의 특징

  1. 중복 키가 추가되면 나중에 추가 된 값이 이전 값을 대체합니다.
  2. 데이터는 추가 순서가 아닌 해시 알고리즘에 저장됩니다.
  3. 추가 된 키는 hashCode 및 equals 메소드를 구현해야합니다.

HashMap의 데이터 구조
1 차원 배열 + 단일 연결리스트 + 레드-블랙 트리
여기에 사진 설명 삽입
HashMap 데이터 저장 과정

  1. 키-값 쌍 데이터를 추가 할 때 먼저 키의 hashCode 메서드를 호출하여 배열 첨자를 계산합니다.
  2. 아래 첨자의 데이터가 비어있는 경우 직접 저장
  3. 아래 첨자에 데이터가있는 경우 호출 된 키의 같음을 해당 위치의 키와 비교합니다.
  4. equals가 true를 반환하면 이전 데이터를 새 데이터로 덮어 씁니다.
  5. equals가 false를 반환하면 이전 데이터 뒤에 새 데이터를 넣어 연결 목록을 만듭니다.
  6. 링크드리스트의 길이가 8을 초과하면 자동으로 red-black tree로 변환 (java8 최적화)

HashMap 소스 코드 분석

//添加数据
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
  Node<K,V>[] tab; Node<K,V> p; int n, i;
  if ((tab = table) == null || (n = tab.length) == 0)
      n = (tab = resize()).length;                  // 获得数组长度
  if ((p = tab[i = (n - 1) & hash]) == null)     //hashCode对数组长度-1取模获得下标i
      tab[i] = newNode(hash, key, value, null);   //该位置为空就直接添加数据
  else {
      Node<K,V> e; K k;
      if (p.hash == hash &&
          ((k = p.key) == key || (key != null && key.equals(k))))  //不为空就调用equals比较键
          e = p;																				 //键相同就赋值给e,后面直接覆盖value
      else if (p instanceof TreeNode)
          e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
      else {
          for (int binCount = 0; ; ++binCount) {
              if ((e = p.next) == null) {
                  p.next = newNode(hash, key, value, null);  //键不相同就放到后面,形成链表
                  if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st    
                      treeifyBin(tab, hash);	   //链表长度超过8,转换为红黑树
                  break;
              }
              if (e.hash == hash &&
                  ((k = e.key) == key || (key != null && key.equals(k))))
                  break;
              p = e;
          }
      }
      if (e != null) { // existing mapping for key
          V oldValue = e.value;
          if (!onlyIfAbsent || oldValue == null)
              e.value = value;        //覆盖旧的value
          afterNodeAccess(e);
          return oldValue;
      }
  }
  ++modCount;
  if (++size > threshold)
      resize();
  afterNodeInsertion(evict);
  return null;
}

해시 테이블

Hashtable과 HashMap의 사용법과 구조는 동일합니다
.

  1. HashMap은 스레드로부터 안전하지 않고 Hashtable은 스레드로부터 안전합니다.
  2. HashMap은 null 키와 값을 추가 할 수 있지만 Hashtable은 null 키와 값을 추가 할 수 없습니다.

TreeMap

特点:添加数据后,会自动对键进行排序
数据结构:红黑树
여기에 사진 설명 삽입
使用时需要注意:

  1. 键必须实现Comparable接口
  2. 键如果和已存在的键相等,TreeMap就放弃添加

LinkedHashMap

继承于HashMap,通过额外的链表保留键的添加顺序。
여기에 사진 설명 삽입

如何选择集合

在开发过程中,需要根据实际业务场景,结合集合的特点选择集合

  • 可以排序,可以添加重复数据,可以随机访问 ----- List
    • 对数据访问要求高 ----- ArrayList
    • 对插入和删除要求高 ----- LinkedList
  • 不能添加重复的数据,不需要随机访问 ------ Set
    • 没有顺序 ----- HashSet
    • 可以进行排序 ----- TreeSet
    • 保留添加顺序 ----- LinkedHashSet
  • 可以进行快速查找 ,以键值对保存------ Map
    • 键没有顺序 ----- HashMap
    • 键可以排序 ----- TreeMap
    • 键保留添加顺序 ----- LinkedHashMap

结束

集合是Java的重点内容,尤其是ArrayList和HashMap这两个集合应用非常广泛,是否掌握了就通过作业检查了。

  1. 定义歌曲类,属性:歌曲名、歌手名、播放时长(int 类型),定义play方法显示歌曲信息。
    1、添加10首歌到ArrayList集合中
    2、遍历所有的歌曲,显示歌曲信息
    3、输入歌曲名,在集合中查找该歌曲
    4、输入整数索引,删除该位置的歌曲
    5、找出播放时间最长的歌曲
    6、将所有歌曲复制到LinkedList集合中
  2. 컬렉션을 HashMap으로 변경하고 노래 이름을 키로 사용하고 노래를 값으로 사용
    1. 컬렉션에 10 곡 추가
    2. 모든 노래를 탐색하고 노래 정보 표시
    3. 노래 이름을 입력하고 검색 컬렉션의 노래.
    4. 노래 이름을 입력, 삭제 노래

다른 Java 지식을 배워야하는 경우 여기 에서 Java 요약에 대한 매우 상세한 지식을 찌르십시오.

추천

출처blog.csdn.net/u013343114/article/details/112602465