JavaSE集合

集合概述

  • 是一个对象。
  • 集合在java中本身是一个容器(来容纳其它类型的数据)。
  • 集合中任何时候存储的都是“引用”。
  • 集合不能直接存储基本数据类型,另外集合也不能直接存储java对象。例如:list.add(100); //自动装箱Integer,存储该对象的引用地址
  • 在java中每一个不同的集合,底层会对应不同的数据结构。
  • 往不同的集合中存储元素,等于将数据放到了不同的数据结构当中。
  • 所有的集合类和集合接口都在java.util包下。
  • 在java中集合分为两大类:
单个方式存储元素 键值对的方式存储元素
单个方式存储元素,这一类集合中超级父接口:java.util.Collection 以键值对的方式存储元素,这一类集合中超级父接口:java.util.Map

一、Collection

  • java.util.Collection

Collection 是 List 和 Set 的父接口,在 Collection 中定义了一些主要方法

方法名 解释
boolean add(E o) 确保此 collection 包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c) 将指定 collection 中的所有元素都添加到此collection 中(可选操作)。
void clear() 移除此 collection 中的所有元素(可选操作)。
boolean contains(Object o) 如果此 collection 包含指定的元素,则返回 true。底层调用的是对象的 equals() 方法
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 中移除指定元素的单个实例,如果存在的话(可选操作)。底层调用了 对象的 equals()方法
boolean removeAll(Collection<?> c) 移除此 collection 中那些也包含在指定 collection中的所有元素(可选操作)。
boolean retainAll(Collection<?> c) 仅保留此 collection 中那些也包含在指定collection 的元素(可选操作)。
int size() 返回此 collection 中的元素数。
Object[] toArray() 返回包含此 collection 中所有元素的数组。
<T> T[] toArray(T[] a) 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

Iterator 接口

关于 Iterator 接口说明,Iterator 称为迭代接口,通过此接口可以遍历集合中的数据,

  • 集合结构改变,必须要重新获取迭代器
  • 此接口主要方法为:
方法名 解释
boolean hasNext() 如果仍有元素可以迭代,则返回 true。
E next() 返回迭代的下一个元素。

迭代器迭代元素的过程中不能使用集合对象的remove方法删除元素,
要使用迭代器Iterator的remove方法来删除元素,防止出现异常:
ConcurrentModificationException

  • ArrayList类 内部实现 Iterator接口的Itr内部类:源码如下
//获得Iterator的方法
    public Iterator<E> iterator() {
        return new Itr();
    }
//Iterator接口的实现类
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

(一)List接口

  • 是一个有序集合,可以放重复的数据,有下标

  • List 接口下面主要有两个实现 ArrayList 和 LinkedList,都是有顺序的,也就是放进去是什么顺序,取出来还是什么顺序,也就是基于线性存储,可以看作是一个可变数组

  • List接口中有一些特有的方法。

方法名 作用
void add(int index, Object element) 在列表中指定的位置上插入指定的元素(可选操作)。插入位置以及后面的元素后移
Object set(int index, Object element) 用指定元素替换此列表中指定位置的元素(可选操作)。
Object get(int index) 返回此列表中指定位置的元素。
int indexOf(Object o) 返回此列表中指定元素的第一个出现的索引,如果此列表不包含元素,返回- 1。
int lastIndexOf(Object o) 返回此列表中指定元素的最后一个发生的索引,如果此列表不包含元素,返回- 1。
Object remove(int index) 移除此列表中指定位置的元素(可选操作)。

1. ArrayList:

查询数据比较快,添加和删除数据比较慢(基于可变数组)

  • ArrayList集合初始化容量10(JDK8中的注释:We distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when first element is added.)
  • 扩容为原容量 1.5 倍。
  • 底层是数组。
  • ArrayList集合末尾增删元素效率还是可以的。

2. LinkedList:

查询数据比较慢,添加和删除数据比较快(基于双向链表数据结构)

3. Vector:

Vector 已经不建议使用,Vector 中的方法都是同步的,效率慢,已经被 ArrayList取代

  • Vector初始化容量是10.
  • 扩容为原容量的 2 倍。
  • 底层是数组。
  • Vector底层是线程安全的。
  • 得到一个线程安全的List: Collections.synchronizedList(list);

4. Stack

是继承 Vector 实现了一个栈,栈结构是后进先出,目前已经被 LinkedList 取代

(二)Set接口

  • 是一个无序集合,不允许放重复的数据

1. 哈希表

  • 哈希表是一种数据结构,哈希表能够提供快速存取操作。哈希表是基于数组,数组内存放单向链表的
  • 缺点,数组一旦创建将不能扩展。

2. HashSet

  • 底层是HashMap
  • HashSet 中的数据是无序的不可重复的。HashSet 按照哈希算法存取数据的,具有非常好性能
  • 它的工作原理是这样的,当向 HashSet 中插入数据的时候,他会调用对象hashCode 得到该对象的哈希码,然后根据哈希码计算出该对象插入到集合中(数组)的位置。
  • 重点:特别是向 HashSet 或 HashMap 中加入数据时必须同时覆盖 equals 和 hashCode 方法,应该养成一种习惯覆盖 equals 的同时最好同时覆盖 hashCode

对象间的比较要求

  • 两个对象 equals 相等,那么它的 hashcode 相等
  • 两个对象 equals 不相等,那么它的 hashcode 并不要求它不相等,但一般建议不相等
  • hashcode 相等不代表两个对象相等(采用 equals 比较)

3. TreeSet 实现SortedSet接口

  • 底层是TreeMap
  • TreeSet 可以对 Set 集合进行排序,默认自然排序(即升序),但也可以做自定义的排序

Comparable 接口

  • 放到 TreeSet 中的对象, TreeSet 会对其进行排序,那么该对象必须必须实现 Comparable 接口,基本类型的包装类和 String 他们都是可以排序的,都实现了 Comparable 接口,重写compareTo() 方法,自定义比较规则

Comparable 和 Comparator 的区别

  • 一个类实现了 Camparable 接口则表明这个类的对象之间是可以相互比较的,这个类对象组成的集合就可以直接使用 sort 方法排序。
  • Comparator 可以看成一种算法的实现,将算法和数据分离(OOP原则),Comparator 也可以在下面两种环境下使用:
    1、类的没有考虑到比较问题而没有实现 Comparable,可以通过 Comparator 来实现排序而不必改变对象本身
    2、可以使用多种排序标准,比如升序、降序等

二、Map

  • java.util.Map;

是一个无序集合,集合中包含一个键对象,一个值对象,键对象不允许重复,值对象可以重复(身份证号—姓名)

  • Map 中可以放置键值对,也就是每一个元素都包含键对象和值对象
  • Map 实现较常用的为HashMap,HashMap 对键对象的存取和 HashSet 一样
  • 采用的是哈希算法,所以如果使用自定类作为 Map 的键对象,必须复写 equals 和hashCode 方法。
  • Map接口中常用方法:
方法名 作用
V put(K key, V value) 向Map集合中添加键值对
V get(Object key) 通过key获取value
void clear() 清空map集合
boolean containsKey(Object key) 如果这Map包含一个指定的键映射返回 true
boolean containsValue(Object value) 如果映射到指定的值的一个或多个键返回 true
boolean isEmpty() 判断Map 集合中元素个数是否为0
Set<K> keySet() 获得Map集合所有的key(所有的建是一个set集合)
V remove(Object key) 通过key删除键值对
int size() 获取Map集合中键值对的个数
Collection<V> values() 获取Map集合中所有的value,返回一个Collection
Set<Map.Entry<K,V>> entrySet() 将Map集合转换为Set集合
  • 遍历Map集合的两种方式

    • 第一种:获取所有key,遍历每个key,通过key获取value.
    • 第二种:获取Set即可,遍历Set集合中的Entry,调用entry.getKey() entry.getValue()
  • put方法和get方法原理
    存放的数据结构是哈希表:一个结点数组,数组里面是单向链表


    • 可以得出,
      • 向Map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法
      • key会被调用hashCode方法和equals方法
      • 同一个单向链表上所有节点的hash相同,因为是同一个数组小标,但同一个链表上的key之间的equals方法 返回值都是false

(一)HashMap类

  • 放在HashMap集合key部分的,以及放在HashSet集合中的元素,因为 HashMap 的底层实现采用的是 hash 表,所以 Map 的 key 必须覆盖hashCode 和 equals 方法
  • JDK8之后的特点:如果哈希表单向链表中元素超过8个,单向链表这种数据结构会变成红黑树数据结构;当红黑树上的节点数量小于6时,会把红黑树变成单向链表数据结构

(二)Hashtable类

  • HashMap和Hashtable的区别
HashMap Hashtable
初始化容量16,扩容2倍 初始化容量11,扩容2倍+1
非线程安全 线程安全
key和value可以为null key和value都不能是null

(三)TreeMap类 实现了SortedMap接口

  • 底层是二叉树
  • treeMap 可以对 Map 中的 key 进行排序,如果 map 中的 key 采用的是自定类那么需要实现Comaprable 或 Comparator 接口完成排序
    • 第一种:实现java.lang.Comparable接口。
    • 第二种:单独编写一个比较器Comparator接口。
  • 自平衡二叉树


    自平衡二叉树

(四)Properties类

  • 是Map集合,继承Hashtable
  • key和value都是string类型
  • 常用两个方法
    • setProperty
    • getProperty
  • 被称为属性类对象
  • 是线程安全的

三、Collections 工具类

Collections 位于 java.util 包中,提供了一系列实用的方法,如:对集合排序,对集合中的内容查找等

  • synchronizedList方法:获得线程安全的集合
  • sort方法(要求集合中元素实现Comparable接口。或者传入一个比较器)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,548评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,497评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,990评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,618评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,618评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,246评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,819评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,725评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,268评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,356评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,488评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,181评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,862评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,331评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,445评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,897评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,500评论 2 359

推荐阅读更多精彩内容

  • 目录 [TOC] 第一章:数据结构基础 1.1-什么是数据结构 ​ 数据结构就是计算机存储、组织数据的方式 。...
    雷哒哒阅读 161评论 0 1
  • JavaSE集合类 概述 Java中集合类概述Java中数组与集合的比较Java中集合框架层次结构 Collect...
    小白菜aaa阅读 244评论 0 0
  • Java 中常见集合 集合这方面的考察相当多,这部分是面试中必考的知识点。 1)说说常见的集合有哪些吧? 1 Co...
    流年划破容颜_cc55阅读 362评论 0 4
  • 集合 定义 集合是一个容器,是用来储存和获取数据的。 它一般用于储存对象 长度可变 集合类体系结构图 Collec...
    北洋同学阅读 327评论 0 2
  • 1. 集合框架 为什么出现集合类?面向对象对事物的体现都是以对象的形式,为了方便对多个对象的操作,就对对象进行存储...
    MrRobot_阅读 519评论 0 0