Day8 集合

Day8 集合

常用集合体系图(中间省略了一些结构)

请添加图片描述

较为完整的体系结构

请添加图片描述

  • List:无序可重复
  • Set:有序不可重复
  • Map:键值对,键不可重复,值可以
常用范围底层实现方式线程是否安全扩容初始值
ArrayList查/改Object数组n1.5倍10
LinkedList添加/删除双向链表和双端队列n链表追加
Vector要求线程安全Object数组y210
HashSet去重HashSetn216
LinkedHashSetLinkedHashMapn216
TreeSet有排序需求TreeMapn
HashMap有键值对需求数组/链表/红黑树n216
HashTable线程安全数组/链表y2倍 + 111
LinkedHashMap数组/链表n216
TreeMap红黑树n
Properties读取配置文件继承自Hashtable,实现了Map

Iterator接口(迭代器)

  • boolean hasNext():如果仍有元素可以迭代,则返回 true。
  • E next():返回迭代的下一个元素。有一个指针指向当前集合头部的上一个空位
  • void remove():删除。移除next指向的那个元素,需要与其连用
  • 可以使用ForEach
public class Chap01 {
    public static void main(String[] args) {
        iteratorText();
    }

    public static void iteratorText(){
        List<Integer> list = new ArrayList<>();
        list.add(1); list.add(2); list.add(3);
        // 生成一个迭代器
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){   // 判断是否存在下一个
            Integer next = iterator.next();   // 指针下移,取值
            System.out.println(next);
        }
    }
}

LinkedList:可以作为List使用,也可以作为Deque使用

public static void linkedListTest(){
    // implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    // 实现了 Deque,相当于可以用队列/栈的方式来操作LinkedList
    Deque<Integer> list = new LinkedList<>();
    list.addFirst(2);
    System.out.println(list.peek());    // 找到头元素
    System.out.println(list.poll());    // 找到并移除头元素
    list.addAll(Arrays.asList(3, 4, 6, 9));   // 添加多个元素
    System.out.println(list.element());    // 找到头元素
    list.offer(10);   // 插入到最后
    for (Integer integer : list) {
        System.out.print(integer + "\t");
    }
    System.out.println(list.pop());   // 弹出
    list.push(12);   // 压入
}

ArrayList(基于jdk8)

  • 底层使用Object数组存储
  • 使用无参构造,初始容量为0,第一次调用add方法时,才初始化容量为10
  • 使用有参构造,直接创建指定容量的数组
  • 都是扩容为原来的1.5倍
  • 可以重复添加null
// 部分源码
private static final int DEFAULT_CAPACITY = 10;   // 初始容量,当调用add方法是才会初始化
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;     // 使用的是Object数组存储
// 无参构造
public ArrayList() {     // 初始容量为0
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 有参构造
public ArrayList(int initialCapacity) {    // 指定初始容量
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

// add方法
public void add(int index, E element) {
    rangeCheckForAdd(index);     
    ensureCapacityInternal(size + 1);  // 检测并初始化容量,默认为10
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}

// 初始化容量
public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        ? 0 : DEFAULT_CAPACITY;   // 如果是无参构造实例化的对象
    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}

// 扩容机制
private void grow(int minCapacity) {     
    int oldCapacity = elementData.length;
    // 扩容为原来的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    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相同,添加了同步机制synchronied,扩容为原来的两倍

LinkedList

  • 底层实现了双向链表和双端队列特点
  • 底层维护了一个双向链表,还维护了两个属性first和last分别指向首结点和尾结点
  • 每个节点,里面又维护了prev、next、item三个属性

HashSet

  • 实例化一个HashSet,其实底层实例化了一个HashMap
  • 可以存放null
  • 第一次add时,才初始化容量为16
  • 每次扩容为原来的两倍
  • 最初是数组存储,当一个存在多个hash值相同,equals不同时,会在当前数组位置建立一条链表存储,当该链表的长度超过了8时,就会将链表改成红黑树来存储
// HashMap的部分源码
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 初始化容量 16
// 用于计算临界值,当  容量 * 加载英子 <= 当前数据 时,就会扩容
static final float DEFAULT_LOAD_FACTOR = 0.75f;   // 加载英子
static final int TREEIFY_THRESHOLD = 8;   // 一个位置上的链表阈值,当超过了这个阈值,就会使用红黑树来存储
static final int UNTREEIFY_THRESHOLD = 6;   // 红黑树的阈值,将红黑树转为链表

LinkedHashSet:底层是一个LInkedHashMap,维护了一个数组+双向链表

TreeSet:保证了插入元素的有序

  • 自然排序:Comparable接口,该接口里定义了一个compareTo方法。使用类去实现该接口
  • 定制排序:Comparator接口,该接口包含一个compare方法,重写该方法,可以使用匿名
// 自然排序
public class Chap02 {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("丰1", 18));
        treeSet.add(new Student("丰1", 17));
        treeSet.add(new Student("丰", 17));
        // [Student{name='丰', age=17}, Student{name='丰1', age=17}, Student{name='丰1', age=18}]
        System.out.println(treeSet);  // 升序
    }
}

class Student implements Comparable<Student>{
    // 实现Comparable接口,自然排序
    private String name;
    private int age;

    // 实现compareTo方法
    @Override
    public int compareTo(Student o) {
        // 模拟age排序
        if (this.age > o.age){
            return 1;
        }else if (this.age < o.age){
            return -1;
        }else{    // 如果相同,可以使用二重排序
            // String 实现了compareTo方法,这里调用的是String的
            if (this.name.compareTo(o.name) > 0){
                return 1;
            }else if (this.name.compareTo(o.name) < 0){
                return -1;
            }
            return 0;
        }
    }
}   // 省略代码
// 定制排序
public class Chap03 {
    public static void main(String[] args) {
        // 定制排序,实现Comparator接口,重写compare方法
        TreeSet<Persons> treeSet = new TreeSet<>(new Comparator<Persons>() {
            @Override
            public int compare(Persons o1, Persons o2) {
                if (o1.getAge() > o2.getAge()){
                    return 1;
                }else if (o1.getAge() < o2.getAge()){
                    return -1;
                }else return 0;
            }
        });
        treeSet.add(new Persons("丰1", 18));
        treeSet.add(new Persons("丰1", 17));
        treeSet.add(new Persons("丰", 17));
        // [Persons{name='丰1', age='17'}, Persons{name='丰1', age='18'}]
        // 因为不可重复,第三个就没有添加进去
        System.out.println(treeSet);
    }
}

class Persons{
    private String name;
    private int age;
}

Hashtable

  • 线程安全
  • 初始化容量为11
  • 扩容为原来的 2倍 + 1
  • 键不允许为null,而HashMap可以

Collections工具类

void reverse(List list)   // 倒序
void shuffle(List list)   // 随机排序
void sort(List list)      // 按自然排序的升序
void sort(List list, Comparator c)   // 定制排序,由Comparator控制排序逻辑
void swap(List list, int i , int j)    // 交换两个索引位置的元素
void rotate(List list, int distance)//旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面
    
int binarySearch(List list, Object key)   // 对List进行二分查找
int max(Collection coll) 
int min(Collection coll, Comparator c)
void fill(List list, Object obj)    // 用指定的元素代替指定list中的所有元素
int frequency(Collection c, Object o)  // 统计元素出现次数
boolean replaceAll(List list, Object oldVal, Object newVal)  // 用新元素替换旧元素
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值