理解java中集合类

集合做为一个工具类,日常撸代码的时候用的还是挺多的,尤其是做一些比赛题啥的,和String类都挺重要的

  • 集合类的框架体系图

常用的一般有ArrayList,LinkedList,HashSet,HashMap

集合特性>

任何一个集合都可以使用Iterator进行迭代遍历,像List这种顺序存储的集合是含有get()方法,Set与Map就没有,要想进行遍历,只能用迭代器进行

一.List

List接口扩展自Collection,它可以定义一个允许重复的有序集合,从List接口中的方法来看,List接口主要是增加了面向位置的操作,允许在指定位置上操作元素,同时增加了一个能够双向遍历线性表的新列表迭代器ListIterator。

1.1ArrayList

/**
     * Appends the specified element to the end of this list.
     *添加制定的元素至该集合的尾部
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        //当要添加一个元素的时候,要判断当前集合数组的长度加一是否符合添加要求
        ensureCapacityInternal(size + 1);  // Increments modCount!!

        //一切的一切(需要扩容吗)判断完之后,将新的元素添加至集合
        elementData[size++] = e;
        return true;
    }
    //
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //当前集合数组里面为空的时候,给定一个长度为10的数组
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);   
            //DEFAULT_CAPACITY静态常量为10
        }
        return minCapacity;
    }
   
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        
        //当要添加的元素添加之后长度要是大于当前集合数组的长度
        //要对集合数组扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
     /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        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);
    }

1.2LinkedList

LinkedList是将元素以链表的方式进行存储,根据使用需要,选择效率较高的类型合适的集合使用

 

二.Set

Set集合与List集合最大的区别就是Set里面不能存放重复的元素,前提是该包装类里面必须重写equals()和HashCode()方法,

java自带的类中当然是已经写过的啦。

2.1 HashSet

当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。

示例:给Set集合里面添加自己创建的类Student,自己重写内部equals()和HashCode()方法,以学生的id为判断标准(即set集合里最终不能含有重复id的元素)

import java.util.*;

public class Set测试 {
    public static void main(String[] args) {
        Set<Student> studentSet = new HashSet<>();
        Student s1 = new Student(2011);
        Student s2 = new Student(2034);
        Student s3 = new Student(1022);
        Student s4 = new Student(1022);
        Student s5 = new Student(2011);
        studentSet.add(s1);
        studentSet.add(s2);
        studentSet.add(s3);
        studentSet.add(s4);
        studentSet.add(s5);

        Iterator<Student> iterator = studentSet.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().getId());
        }
    }
}
import java.util.Objects;

public class Student {
    private int id;

    public Student() {
    }

    public Student(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return id == student.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

2.2 TreeSet

树形集是一个有序的Set,其底层是一颗树,这样就能从Set里面提取一个有序序列了。在实例化TreeSet时,我们可以给TreeSet指定一个比较器Comparator来指定树形集中的元素顺序,或者自定义类实现Comparable接口,重写内部的compareTo方法。树形集中提供了很多便捷的方法。

而TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。向 TreeSet中加入的应该是同一个类的对象。TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0。

 

示例>同样是添加Student进Set中,此次除重并按照学号大小进行排序

import java.util.Objects;

public class Student implements Comparable<Student> {
    private int id;

    public Student() {
    }

    public Student(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public int compareTo(Student o) {
        if (this.id > o.id) {
            return 1;
        } else if (this.id < o.id) {
            return -1;
        }
        return 0;
    }
}
import java.util.*;

public class Set测试 {
    public static void main(String[] args) {
        Set<Student> studentSet = new TreeSet<>();
        Student s1 = new Student(2011);
        Student s2 = new Student(2034);
        Student s3 = new Student(1022);
        Student s4 = new Student(1022);
        Student s5 = new Student(2011);
        studentSet.add(s1);
        studentSet.add(s2);
        studentSet.add(s3);
        studentSet.add(s4);
        studentSet.add(s5);
        Iterator<Student> iterator = studentSet.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().getId());
        }
    }
}

三.Map

数组的元素类型是Node<K,V>,Node<K,V>继承自Map.Entry<K,V>,表示键值对映射。

一个键对应一个值,值可以一样,但键必须唯一

Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable。

TreeMap是有序的,HashMap和HashTable是无序的
Hashtable的方法是同步的,HashMap的方法不是同步的。这是两者最主要的区别。
这就意味着:

Hashtable是线程安全的,HashMap不是线程安全的。
HashMap效率较高,Hashtable效率较低。
如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有。
Hashtable不允许null值,HashMap允许null值(key和value都允许)
父类不同:Hashtable的父类是Dictionary,HashMap的父类是AbstractMap

3.1 TreeMap

存储为红黑树,也就是平衡排序二叉树

主要功能用于排序,与TreeSet一样,想要给自定义的类进行排序的话,还得实现Comparable接口,实现compareTo方法

示例>无序的学生id,按照从小到大的顺序排序,最后分别输出学号,姓名,学号和姓名

import java.util.*;

public class Map测试 {
    public static void main(String[] args) {
        Map<Student, String> studentStringMap = new TreeMap<>();
        studentStringMap.put(new Student(20), "张三");
        studentStringMap.put(new Student(30), "李四");
        studentStringMap.put(new Student(10), "王二麻");
        studentStringMap.put(new Student(5), "小卓子");
        //输出所有的键
        Iterator<Student> studentIterator = studentStringMap.keySet().iterator();
        while (studentIterator.hasNext()) {
            System.out.println(studentIterator.next().getId());
        }
        //输出所有的值
        Iterator<String> stringIterator = studentStringMap.values().iterator();
        while (stringIterator.hasNext()) {
            System.out.println(stringIterator.next());
        }
        //输出键值所有
        Iterator<Map.Entry<Student, String>> entryIterator = studentStringMap.entrySet().iterator();
        while (entryIterator.hasNext()) {
            Map.Entry<Student, String> temp = entryIterator.next();
            System.out.println(temp.getKey().getId() + ":" + temp.getValue());
        }
    }
}

3.2 HashMap

通用的存储键值对的集合

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值