Java基础总结记录(五):集合

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a913858/article/details/88088745

集合类在应用中常常用到,里面的知识也是比较多的,总结一下常用的一些集合类。
一、集合图
在这里插入图片描述
针对这张图来展开集合之路。
二、Collections
这个类是个工具类用来服务我们的集合类的,里面的方法本人没有一一用过,也说不好,我就把一些可能会用到的方法拿出来说下,顺便加深下集合类的记忆。
1.排序

	@SuppressWarnings({"unchecked", "rawtypes"})
    public static <T> void sort(List<T> list, Comparator<? super T> c) {
        Object[] a = list.toArray();
        Arrays.sort(a, (Comparator)c);
        ListIterator<T> i = list.listIterator();
        for (int j=0; j<a.length; j++) {
            i.next();
            i.set((T)a[j]);
        }
    }

这是collections.sort的源码,通过源码我们可以看出来传入两个对象一个list,一个Comparator。至于再深入大家自行源码看看吧。然后编写咱们的list的排序

public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(3);
		list.add(4);
		list.add(5);
		list.add(2);
		System.out.println(list);
		
		Collections.sort(list,new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2.compareTo(o1);//倒序
//				return o1.compareTo(o2);//正序
			}
		});
		System.out.println(list);
	}

控制台打印的结果:

[1, 3, 4, 5, 2]
[5, 4, 3, 2, 1]

2.copy方法
源码

public static <T> void copy(List<? super T> dest, List<? extends T> src) {
        int srcSize = src.size();
        if (srcSize > dest.size())
            throw new IndexOutOfBoundsException("Source does not fit in dest");

        if (srcSize < COPY_THRESHOLD ||
            (src instanceof RandomAccess && dest instanceof RandomAccess)) {
            for (int i=0; i<srcSize; i++)
                dest.set(i, src.get(i));
        } else {
            ListIterator<? super T> di=dest.listIterator();
            ListIterator<? extends T> si=src.listIterator();
            for (int i=0; i<srcSize; i++) {
                di.next();
                di.set(si.next());
            }
        }
    }

接下来是自己写的copy方法

List src = new ArrayList();
src.add("西部落酋长");
List dest = new ArrayList();
Collections.addAll(dest, new String[src.size()]);
		
Collections.copy(dest, src);
System.out.println(dest);

结果:[西部落酋长]
三、List
根据上图我们可以看到List下面有三个实现类,当然也不值这三个类,还有其他好多就不多说了。
1.ArrayList
首先它是基于数组的存储结构,根据索引可以快速读取,所以查询速度快。那么进行添加的速度,如果从中间数组添加数据或者删除数据,需要对数组进行复制、移动、代价比较高。所以速度要慢。
当我们添加一个或者多个元素的时候,数组长度不够时,就扩容,这里有两种情况:
只添加一个元素,例如:原来数组的capacity为10,size已经为10,不能再添加了。需要扩容,新的capacity=old capacity+old capacity>>1=10+10/2=15.即新的容量为15。
当同时添加多个元素时,原来数组的capacity为10,size为10,当同时添加6个元素时。它需要的min capacity为16,而按照capacity=old capacity+old capacity>>1=10+10/2=15。new capacity小于min capacity,则取min capacity。
对于添加,如果不指定下标,就直接添加到数组后面,不涉及元素的移动,如果要添加到某个特定的位置,那需要将这个位置开始的元素往后挪一个位置,然后再对这个位置设置。
2.LinkedList
首先它是基于链表的,它是个双向链表,无序的。优点,增加删除,用时间很短,但是因为没有索引,对索引的操作,比较麻烦,只能循环遍历,但是每次循环的时候,都会先判断一下,这个索引位于链表的前部分还是后部分,每次都会遍历链表的一半 ,而不是全部遍历。LinkedList是一个无序的链表,按照插入的先后顺序排序,不提供sort方法对内部元素排序。
3.Vector
首先它也是基于数组操作,但是它是线程同步的,所以它是线程安全的,但是效率要比ArrayList要低。如果不考虑线程安全问题,就用ArrayList,考虑就用vetor.

vector

public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        ensureCapacityHelper(elementCount + 1);
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    }

ArrayList

public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

LinkedList

public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }

再往底层就不一一列举了,可以自行查看。
四、Set
然后来看Set
1.HashSet
我们都知道Set的特点就是无序,无重复。HashSet 底层是通过哈希表存储的,那就是hashMap.我们看下源码实现

public HashSet() {
        map = new HashMap<>();
    }

当然它跟HashMap还是有区别,hashMap是key–value形式的,HashSet只是存储了不重复的key信息。它是非线程安全的。
2.TreeSet
与hashset采用hash算法决定元素的存储位置,TreeSet采用红黑树的数据结构来存储集合元素。根据key来进行排序,默认是升序排序,不允许key值为空。非线程安全。
调用TreeSet的无参的构造器,并实现Comparable接口,实现里的 compareTo(Object obj)方法,来比较集合元素的大小,然后按照compareTo里的排序。
3.LinkedHashSet
底层采用双向链表实现,可以保证元素的插入顺序,又因为是HashSet的子类,所以插入的元素不能重复。
五、Map
1.HashMap
根据键的hascode存储,可以根据键可以快速获取它,具有很快的访问速度,非同步允许Null,我们知道hashMap存储方式是key–value.,遍历map我们知道很多种方法,曾经在面试中碰到这个一个面试题:
问:entrySet和keySet都是遍历map的这两个有啥区别?
答:entrySet可以一次就取出map的值,而keySet需要遍历两次,一次是转化iterator,再一次才能从中取出。.
2.TreeMap
有序的key-value集合,红黑数排序时,根据Entry中的key进行排序;Entry中的key比较大小是根据比较器comparator来进行判断的。
3.HashTable
和HashMap一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射。Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。此外,Hashtable中的映射不是有序的。

扫描二维码关注公众号,回复: 5483659 查看本文章

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/a913858/article/details/88088745