초보 자 자바 집합 기초 지식 이해

개술
집합 은 길이 가 변 하고 데 이 터 를 저장 하 는 데이터 구조 가 다양 하 며 저장 대상 이 다양한 데이터 용기 이다.자바 의 집합 은 List 집합,Set 집합,HashMap 집합 등 으로 나 눌 수 있다.
자바 집합 시스템 구조:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-abSCHb0c-1623645339249)(C:\Users\52425\Desktop\1.png)]
2.컬 렉 션
collection 은 자바 의 모든 값 저장 집합 을 위 한 최고급 인터페이스 이기 때문에 모든 직접적 이거 나 간접 적 인 실현 류 는 비 개인 적 인 방법 이 있 습 니 다.우 리 는 그 방법 부터 이 시스템 의 기능 실현 을 이해 할 수 있 습 니 다.

 boolean add(E e) 
              collection        。 
 boolean addAll(Collection<? extends E> c) 
              collection             collection  。 
 void clear() 
              collection       。 
 boolean contains(Object o) 
              collection        ,    true。 
 boolean containsAll(Collection<?> c) 
              collection      collection       ,    true。 
 boolean equals(Object o) 
              collection          。 
 int hashCode() 
              collection      。 
 boolean isEmpty() 
              collection      ,    true。 
 Iterator<E> iterator() 
               collection             。 
 boolean remove(Object o) 
             collection             ,      )。 
 boolean removeAll(Collection<?> c) 
              collection           collection       。 
 boolean retainAll(Collection<?> c) 
               collection           collection    。 
 int size() 
              collection      。 
 Object[] toArray() 
                collection         。 
<T> T[] 
 toArray(T[] a) 
                collection         ;                       。 
1、List
List 는 단일 열 집합 으로 질서 있 는 데 이 터 를 삽입 하고 데 이 터 를 반복 할 수 있 습 니 다.
리스트 집합
  • LinkedList
  • ArrayList
  • 1)ArrayList
    예시:
    
    public class CollectionTest {
        public static void main(String[] args) {
            List list = new ArrayList();
            //    ,boolean add(E e)     collection        
            list.add("  ");
            list.add(1);
            list.add('A');
            System.out.println(list);//[  , 1, A]
            //boolean addAll(Collection<? extends E> c)
            //              collection             collection  
            List list1 = new ArrayList();
            list.add("java");
            list.add("MySQL");
            list.addAll(list1);
            System.out.println(list);//[  , 1, A, java, MySQL]
            //boolean contains(Object o)
            //              collection        ,    true。
            System.out.println(list.contains("java"));//true
            //boolean remove(Object o)
            //             collection             ,      )。
            System.out.println(list.remove("java"));//true
            // int size()
            //              collection      。
            System.out.println(list.size());//4
            //set(int index, E element)
            //                              。
            //        
            System.out.println(list.set(1, "  "));
            //get(int index) 
            //                        。
            System.out.println(list.get(1));
            // Iterator<E> iterator()
            //               collection             。
            //     
            Iterator iterator = list.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
        }
    
    설명:Array List 바 텀 은 배열 의 형식 으로 집합 을 만 들 기 때문에 배열 의 특성 을 바탕 으로 이 집합 은 데이터 에 대한 검색 이 빠 르 지만 대량의 데 이 터 를 삭제 하거나 이동 하 는 작업 이 느 려 집 니 다.그것 은 빠 른 검색 에 적합 하지만 삭제 작업 은 적합 하지 않다.
    2)LinkedList
    LinkedList:양 방향 링크 는 내부 에 배열 을 설명 하지 않 고 Node 형식의 first 와 last 를 정의 하여 첫 번 째 요 소 를 기록 하 는 데 사 용 됩 니 다.또한 내부 클래스 노드 를 정의 하여 링크 드 리스트 에 데 이 터 를 저장 하 는 기본 구조 로 합 니 다.Node 는 데 이 터 를 저장 하 는 것 외 에 두 개의 변 수 를 정의 합 니 다.
  • prev 변 수 는 이전 요소 의 위 치 를 기록 합 니 다
  • next 변 수 는 다음 요소 의 위 치 를 기록 합 니 다
  • 특징:
  • 데이터 질서
  • 바 텀 구 조 는 링크
  • 이다.
    ArrayList 비교:
  • LinkedList 의 추가 요소 속도 가 ArrayList 보다 빠르다.
  • LinkedList 의 조회 속 도 는 ArrayList 보다 느리다.
  • 바 텀 데이터 구조 가 다르다.LinkedList 는 링크 구 조 를 사용 하고 ArrayList 바 텀 은 배열 구 조 를 사용한다.
  • 설명:LinkedList 는 일반적으로 빈번 한 조작 을 추가 하 는 데 사용 되 며,ArrayList 는 빈번 한 조회 에 사용 된다.

    예시:
    
    public class Stack {
        private LinkedList data = null;
        public Stack(){
            data = new LinkedList();
        }
        //     
        public boolean push(Object element) {
            data.addFirst(element);
            return true;
        }
        //     
        public Object pop() {
            return data.pollFirst();
        }
        //         
        public boolean isEmpty() {
            return data.isEmpty();
        }
        //     
        public void list() {
            Iterator it = data.iterator();
            while(it.hasNext()){
                System.out.println(it.next());
            }
        }
    }
    public class MyStack {
        public static void main(String[] args) {
            Stack stack = new Stack();
            stack.push("  ");
            stack.push("  ");
            stack.push("  ");
            stack.list();
            System.out.println("-------------");
            Object pop = stack.pop();
            System.out.println(pop);
        }
    }
    
    2、set
    1)HashSet
    HashSet 은 Set 인터페이스의 전형 적 인 실현 으로 대부분 Set 집합 을 사용 할 때 이 실현 류 를 사용한다.
  • HashSet 은 Hash 알고리즘 에 따라 집합 중의 요 소 를 저장 하기 때문에 액세스,검색,삭제 성능 이 좋 습 니 다.
  • HashSet 은 다음 과 같은 특징 을 가진다.원소 의 배열 순 서 를 보장 할 수 없다
  • HashSet 은 스 레 드 가 안전 하지 않 습 니 다
  • 집합 요 소 는 null
  • 일 수 있다.
  • 중복 요 소 를 추가 할 수 없습니다
  • HashSet 집합 은 두 요소 가 동일 하 다 고 판단 하 는 기준 이다.두 대상 은 hashCode()방법 을 통 해 비교적 같 고 두 대상 의 equals()방법 반환 값 도 같다.
  • Set 용기 에 저 장 된 대상 에 대해 해당 하 는 클래스 는 반드시 equals()와 hashCode(Object obj)방법 을 다시 써 서 대상 과 같은 규칙 을 실현 해 야 한다.즉,"같은 대상 은 반드시 같은 해시 코드 를 가 져 야 한다."
  • 예시:
    
     public static void main(String[] args) {
            Set set = new HashSet();
            //   
            // boolean add(E e) :            
            set.add("hello");
            set.add("world");
            set.add("world");
            set.add(null);
            System.out.println(set);
            //  :Set        ,      
            // boolean addAll(Collection<? extends E> c) :            
            Set set1 = new HashSet();
            set1.add("aaa");
            set1.add("linux");
            ;
            set.addAll(set1);
            System.out.println(set);
            // boolean remove(Object o) :          
            set.remove("hello");
            System.out.println(set);
            // boolean removeAll(Collection<?> c) :                
            set1.add("aaa");
            set1.add("linux");
            set.removeAll(set1);
            System.out.println(set);
            // void clear() :         
            set.clear();
            System.out.println(set);
            // int size() :         
            int size = set.size();
            System.out.println(size);
            // boolean contains(Object o) :             ,   true,   false;
            System.out.println(set.contains("aaa"));
    
            // boolean isEmpty() :        
            System.out.println(set.isEmpty());
        }
    
    설명:HashSet 에 요 소 를 추가 할 때 먼저 두 요소 의 hashCode 값 이 같 지 않 은 것 을 비교 하고 같 지 않 으 면 직접 추가 합 니 다.만약 같다 면 두 원소 의 equals 값 이 같 는 지 다시 판단 하고,같 으 면 추가 하지 않 으 며,같 지 않 으 면 추가 합 니 다.
    2)TreeSet
  • TreeSet 과 TreeMap 은 빨 간 검 은 나무의 저장 구 조 를 사용한다
  • 특징:질서 가 있 고 조회 속도 가 List 보다 빠르다
  • TreeSet 집합 을 사용 하 는 것 은 대상 이 비교 가능 해 야 한 다 는 것 이다.대상 을 비교 할 수 있 도록 하 는 방법 은 두 가지 가 있다.
    첫 번 째:Comparable인 터 페 이 스 를 실현 하고 다시 쓰기compareTo()방법:
    두 번 째:비교 기 류 를 써 서Comparator인 터 페 이 스 를 실현 하고 다시 쓰기comare()방법 을 사용한다.
    예시:
    1.실체 클래스
    
    public class Student implements Comparable<Student>{
        private String name;
        private int age;
        private String sex;
        private int height;
    
        public Student() {
        }
        public Student(String name, int age, String sex, int height) {
            this.name = name;
            this.age = age;
            this.sex = sex;
            this.height = height;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
        public int getHeight() {
            return height;
        }
        public void setHeight(int height) {
            this.height = height;
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Student student = (Student) o;
            return age == student.age &&
                    height == student.height &&
                    Objects.equals(name, student.name) &&
                    Objects.equals(sex, student.sex);
        }
        @Override
        public int hashCode() {
            return Objects.hash(name, age, sex, height);
        }
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", sex='" + sex + '\'' +
                    ", height=" + height +
                    '}';
        }
    
        @Override
        public int compareTo(Student stu) {
            if (stu.getAge() > this.getAge()){
                return 1;
            }
            if (stu.getAge() < this.getAge()){
                return -1;
            }
            return stu.getName().compareTo(this.getName());
        }
    }
    
    2.테스트 클래스:
    
    public class TreeSetTest {
        public static void main(String[] args) {
    
            TreeSet treeSet = new TreeSet();
            Student student1 = new Student("  ", 20, " ", 165);
            Student student2 = new Student("  ", 21, " ", 170);
            Student student3 = new Student("  ", 19, " ", 160);
            Student student4 = new Student("  ", 18, " ", 165);
            Student student5 = new Student("  ", 20, " ", 175);
            treeSet.add(student1);
            treeSet.add(student2);
            treeSet.add(student3);
            treeSet.add(student4);
            treeSet.add(student5);
            System.out.println(treeSet);
        }
    }
    
    3.실체 류
    
    public class Teacher {
        private String name;
        public Teacher(){}
        public Teacher(String name){
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Teacher{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    4.테스트 클래스
    
    public class TreeSetTest2 {
        public static void main(String[] args) {
            Teacher teacher1 = new Teacher("11");
            Teacher teacher2 = new Teacher("12");
            Teacher teacher3 = new Teacher("13");
            Teacher teacher4 = new Teacher("14");
            Teacher teacher5 = new Teacher("15");
            TreeSet treeSet1 = new TreeSet(new  Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    return o1.hashCode() - o2.hashCode();
                }
            });
            treeSet1.add(teacher1);
            treeSet1.add(teacher2);
            treeSet1.add(teacher3);
            treeSet1.add(teacher4);
            treeSet1.add(teacher5);
            System.out.println(treeSet1);
        }
    }
    
    설명:HashSet무 게 를 빼 는 것 은hashCodeequals()방법 에 의존 하 는 것 이 고,TreeSet 무 게 를 빼 는 것 은 비교 기 에 의존한다.
    지도
    저 장 된 두 열 요 소 는 Key 는 무질서 하고 중복 할 수 없 으 며 Value 는 무질서 하고 중복 할 수 있 습 니 다.
    1、HashMap
    
    public class HashMapDemo {
        private Map map = null;
        public void init() {
            map = new HashMap();
            map.put("a", "aaa");
            map.put("b", "bbb");
            map.put("c", "ccc");
            System.out.println(map);
        }
        //     
        public void testPut() {
            // V put(K key, V value) :    key value      
            map.put("a1", "aaa");
            map.put("b1", "bbb");
            map.put("c1", "ccc");
            System.out.println(map);
            // void putAll(Map<? extends K,? extends V>m) :          
            Map map1 = new HashMap();
            map1.put("e", "eee");
            map1.put("f", "fff");
            map.putAll(map1);
            System.out.println(map);
            // default V putIfAbsent(K key, V value) :  key      
            map.putIfAbsent("a", "hello");
            System.out.println(map);
            map.putIfAbsent("g", "ggg");
            System.out.println(map);
        }
        //     
        public void testModify() {
            // V put(K key, V value) :      key         
            map.put("a", "hello");
            map.put("a", "world");
            System.out.println(map);
            //   , key   ,           。
            // default V replace(K key, V value) :  key    ,       
            Object replace = map.replace("b1", "java");
            System.out.println(replace);
            System.out.println(map);
            //default boolean replace(K key, V oldValue,V newValue)
        }
        //     
        public void testRemove() {
            // V remove(Object key) :    key         
            Object c = map.remove("c");
            System.out.println(c);
            System.out.println(map);
            // default boolean remove(Object key, Objectvalue) :  key value    
            map.remove("b", "bbb1");
            System.out.println(map);
            // void clear() :         
            map.clear();
            System.out.println(map);
        }
        //     
        public void testJudge() {
            // boolean isEmpty() :        ,     true,    false
            System.out.println(map.isEmpty());
            // boolean containsKey(Object key) :            key,    true,    false
            boolean flag = map.containsKey("a");
            System.out.println(flag); // true
            flag = map.containsKey("a1");
            System.out.println(flag); // false
            // boolean containsValue(Object value) :            value,    true,    false
            flag = map.containsValue("aaa");
            System.out.println(flag); // true
            flag = map.containsValue("aaa1");
            System.out.println(flag); // false
        }
        //     
        public void testGet() {
            // int size() :         
            int size = map.size();
            System.out.println(size);
            // V get(Object key) :  Key   ,           ,    null
            Object val = map.get("a");
            System.out.println(val);
            val = map.get("a1");
            System.out.println(val); // null
            // default V getOrDefault(Object key, VdefaultValue) :  Key   ,  key   ,      
            val = map.getOrDefault("a1", "hello");
            System.out.println(val);
            // Collection<V> values() :        Value
            Collection values = map.values();
            for (Object value : values) {
                System.out.println(value);
            }
            // Set<K> keySet() :        Key
            Set set = map.keySet();
            for (Object o : set) {
                System.out.println(o);
            }
        }
        //     
        public void testIterator() {
            //    :  key      
            Set keySet = map.keySet();
            Iterator it = keySet.iterator();
            while (it.hasNext()) {
                Object key = it.next();
                Object val = map.get(key);
                System.out.println(key + "=" + val);
            }
            System.out.println("------------------------ ");
            //    :  for  
            for (Object key : map.keySet()) {
                System.out.println(key + "=" +
                                   map.get(key));
            }
            System.out.println("------------------------ ");
            //    :  Map          ,        
            Set entrySet = map.entrySet();
            for (Object obj : entrySet) {
                Map.Entry entry = (Map.Entry) obj;
                System.out.println(entry.getKey() + "=" +
                                   entry.getValue());
            }
        }
    }
    
    설명:HashMap 에서 키-값 은 비어 있 지만 키 가 유일 하고 값 은 중복 가능 합 니 다.hashMap 은 라인 이 안전 하지 않 습 니 다.
    2、TreeMap
    질서 있 는 집합 입 니 다.기본적으로 자연 정렬 방식 을 사용 합 니 다.
    
    public class Person implements Comparable {
        private String name;
        private int age;
        @Override
        public int compareTo(Object o) {
        if (o instanceof Person) {
        Person p = (Person) o;
        return this.age - p.age;
        }
        return 0;
    }
        public Person() {}
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public String toString() {
            return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
        }
    }
    
    테스트
    
    public class TeeMapDemo {
        @Test
        public void testInteger() {
            TreeMap tm = new TreeMap();
            tm.put(3, 333);
            tm.put(2, 222);
            tm.put(11, 111);
            tm.put(2, 222);
            System.out.println(tm);
        }
        @Test
        public void testString() {
            TreeMap tm = new TreeMap();
            tm.put("hello", "hello");
            tm.put("world", "world");
            tm.put("about", "");
            tm.put("abstract", "");
            System.out.println(tm);
        }
        @Test
        public void testPerson() {
            TreeMap tm = new TreeMap(new Comparator(){
                @Override
                public int compare(Object o1, Object o2) {
                    if (o1 instanceof Person && o2
                        instanceof Person) {
                        Person p1 = (Person) o1;
                        Person p2 = (Person) o2;
                        return p1.getAge() - p2.getAge();
                    }
                    return 0;
                }
            });
            tm.put(new Person("  ",18), null);
            tm.put(new Person("  ",17), null);
            System.out.println(tm);
        }
    }
    
    설명:위의 코드 를 통 해 알 수 있 듯 이 TreeMap 의 사용 은 TreeSet 의 사용 과 매우 비슷 하 다.HashSet 집합 소스 코드 를 살 펴 보면 HashSet 집합 을 만 들 때 사실은 바 텀 에서 HashMap 을 사용한다.
    
    public HashSet() {
    	map = new HashMap<>();
    }
    
    HashSet 은 실제로 HashMap 의 Key 를 저장 합 니 다.
    3.ConcurrentHashMap
    맵 집합 에서 우 리 는HashMap,TreeMap을 소 개 했 는데 다 중 라인 의 경우 이 집합 들 은 모두 라인 이 안전 하지 않 기 때문에 라인 이 안전 한 문제 가 발생 할 수 있다.
    자바 에서 Hashtable 은 일종 의 스 레 드 안전HashMap이다.Hashtable방법 상HashMap과 다 르 지 않 고 방법 에 만 사용synchronized하여 스 레 드 안전 의 목적 을 달성 했다.우 리 는 Hashtable 의 소스 코드 를 관찰 했다.
    
        public synchronized V get(Object key) {
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % tab.length;
            for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
                if ((e.hash == hash) && e.key.equals(key)) {
                    return (V)e.value;
                }
            }
            return null;
        }
    
    이상 은 Hashtable 의 get 소스 코드 입 니 다.이것 은 방법 에 만 자 물 쇠 를 추가 한 것 임 을 알 수 있 습 니 다.이것 은 스 레 드 의 집행 효율 을 크게 낮 추고 효율 을 희생 하 는 형식 으로 목적 을 달성 하 는 것 입 니 다.이것 은 우리 가 실제 적 으로 원 하 는 것 이 아니 기 때문에 우 리 는 스 레 드 안전 에 있어 보장 되 고 효율 적 으로 도 가능 한 방법 이 필요 합 니 다.
    Concurrent HashMap 은 세그먼트 잠 금 의 원 리 를 사용 하여 소스 코드 를 관찰 합 니 다.
    
     public V put(K key, V value) {
            return putVal(key, value, false);
        }
    final V putVal(K key, V value, boolean onlyIfAbsent) {
            if (key == null || value == null) throw new NullPointerException();
            int hash = spread(key.hashCode());
            int binCount = 0;
            for (Node<K,V>[] tab = table;;) {
                Node<K,V> f; int n, i, fh;
                if (tab == null || (n = tab.length) == 0)
                    tab = initTable();
                else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
                    if (casTabAt(tab, i, null,
                                 new Node<K,V>(hash, key, value, null)))
                        break;                   // no lock when adding to empty bin
                }
                else if ((fh = f.hash) == MOVED)
                    tab = helpTransfer(tab, f);
                else {
                    V oldVal = null;
                    synchronized (f) {
                        if (tabAt(tab, i) == f) {
                            if (fh >= 0) {
                                binCount = 1;
                                for (Node<K,V> e = f;; ++binCount) {
                                    K ek;
                                    if (e.hash == hash &&
                                        ((ek = e.key) == key ||
                                         (ek != null && key.equals(ek)))) {
                                        oldVal = e.val;
                                        if (!onlyIfAbsent)
                                            e.val = value;
                                        break;
                                    }
                                    Node<K,V> pred = e;
                                    if ((e = e.next) == null) {
                                        pred.next = new Node<K,V>(hash, key,
                                                                  value, null);
                                        break;
                                    }
                                }
                            }
                            else if (f instanceof TreeBin) {
                                Node<K,V> p;
                                binCount = 2;
                                if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
                                                               value)) != null) {
                                    oldVal = p.val;
                                    if (!onlyIfAbsent)
                                        p.val = value;
                                }
                            }
                        }
                    }
                    if (binCount != 0) {
                        if (binCount >= TREEIFY_THRESHOLD)
                            treeifyBin(tab, i);
                        if (oldVal != null)
                            return oldVal;
                        break;
                    }
                }
            }
            addCount(1L, binCount);
            return null;
        }
    
    원본 코드 에서 알 수 있 듯 이ConcurrentHashMap는 현재 데 이 터 를 조작 할 때 만 자 물 쇠 를 추가 하여 효율 이 크게 향상 되 었 다.
    스 레 드 가 안전 한 상황 에서 효율 을 높 였 다.
    총결산
    이 글 은 여기까지 입 니 다.당신 에 게 도움 이 되 기 를 바 랍 니 다.또한 당신 이 우리 의 더 많은 내용 에 관심 을 가 져 주 기 를 바 랍 니 다!

    좋은 웹페이지 즐겨찾기