程序员

单列集合

2019-02-26  本文已影响0人  我是java程序员

单列集合

List集合

 1.List常见集合ArrayList和LinkedList

  1.ArrayList是一种单列集合,存储元素可以是任意类型,其有序,有索引,元素线性存储,占据一片连续存储单元,存入顺序和取出顺序一样,因为其底层是通过数组来实现的,Object[]数组 。另外,ArrayList最大的特点是有序,元素可重复,查找快,增删慢。因为底层是数组,通过索引很容易就找到元素,但增删的时候除头尾元素都需要移动大量元素,效率很低。
  2.LinkedList同样是一种单列集合,存储元素可以是任意类型,其有序,但没有索引,或者说不像ArrayList那样的索引,元素线性存储,随即占据存储单元,底层是使用双向链表来实现的。另外,LinkedList最大的特点是有序,元素可重复,但查找慢,增删快,增删时只需移动指针域指向对象就可以了,但查找时需要顺着指针域依次遍历找元素,效率很低。

 2.ArrayList,LinkedList与Vector的比较

  提到ArrayList那就不得不提Vector,前者是线程不同步,即线程不安全的,即任意时刻任意对象都可以操作ArrayList中的元素,但Vector不行,Vector是线程同步的,任意时刻只能有一个对象操作集合中的元素,以保证集合中的元素在使用时不会被其他对象任意改动操作,Vector是栈Stack的底层较好的实现。那么提到线程安全那就不得不提并行和并发(这里只针对于线程,不针对其他),并行是指同一时刻有两个或者两个以上线程同时运行,并发是指多个线程在很短的时间间隔内交替执行。如果是并发,两个,或者多个线程去操作同一个ArrayList集合时,会造成前后读取不一致,这也就导致线程不安全。想要线程安全,ArrayList可以通过Collections工具类的对应synchronized方法来创建集合就是线程安全的。LinkedList同理。不再赘述。

 3.常用方法

import java.util.*;

public class Demo01List {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("ccc");
        //指定位置添加元素
        list.add(1,"bbb");
        //获取元素
        String s = list.get(2);
        //删除元素
        String remove = list.remove(2);//被删除的元素
        //修改元素
        String update = list.set(1, "ddd");//修改前元素内容
        //将其他集合转为list集合如set集合,很重要
        Set<String> set = new HashSet<>();
        set.add("1234");
        set.add("5678");
        List<String> list1 = new ArrayList<>();
        list1.addAll(set);
        System.out.println(list1);//结果输出:[1234, 5678]
        //元素第一次出现的位置。
        list1.add("5678");
        System.out.println(list1.indexOf("5678"));//结果输出:1
        //转为数组
        Object[] objects =  list1.toArray();
        //是否包含元素
        boolean contains = list1.contains("1234");
        //排序,使用的是1.8新特性,引用。
        list1.addAll(list);
        list1.add("1111");
        list1.sort(String::compareTo);
        System.out.println(list1);//结果输出:[1111, 1234, 5678, 5678, aaa, ddd]
    }
}

Set集合

 1.HashSet,LinkedHashSet,TreeSet

  Set单列集合不像LIst集合有序可重复,Set集合内的元素是无序,不可重复的。那么Set集合和List集合都是添加元素,那么是怎么保证元素不重复的呢?答案是底层涉及到了equals方法,如果Set集合内的类型元素没有重写equals方法,那么Set集合也是无法保证元素是我们所想的那样,即两个元素所有属性都相等,两个对象就相等,而是只能如Object类equals方法一样,两个比较的对象必须是同一个对象才相等,所以要想使用Set集合存储某一类对象,该类除特殊情况必须是要重写equals方法的。那么说到equals方法,那么不得不说hashCode方法,为什么重写equals方法要重写hashCode方法呢?原因很简单,equals方法效率太低了,他是对该类对象的所有属性慢慢一 一比较才能得出两个对象是否相等,这个效率太低了,不能处理数据量大的情况,那么jdk为我们提供了另一种比较方法,hashCode方法,他是根据对象创建时对对象所有属性的ASCII码进行一种特殊运算来得到一个值(具体可以看源码),这个值就是哈希值,当两个对象的哈希值不同,那么这两个对象肯定不同,这个很容易明白,可当两个对象的哈希值相同时,则不能判定两个对象一定相同,因为哈希值运算操作中不能保证所有运算的哈希值不同,所以当两个对象的哈希值相同时,还要调用equals方法比较,挨个比较所有属性值才能确定两个对象是都否等。所以综上所述,重写equals方法,可以不用重写hashCode方法,但这样效率很低,不能处理数据量大的情况,所以一般重写了equals方法我们都会重写hashCode方法来提高效率(当然哈希值很难有重复的,只要不刻意一般都不会碰到哈希值相同的情况)。这样就很好的保证了Set集合的不可重复。了解了Set集合的特性,那么来了解下常用Set集合子类。HashSet:1.8以前底层通过数组 + 链表 1.8以后是通过 数组 + 链表 + 红黑树来实现的。当哈希值不同时,HashSet直接将元素存入数组中,但当哈希值相同时,则是使用链表将哈希值相同元素连接起来构成一个链表,(可以想象一下就是将哈希值相同的元素弄成了一条长链,挂在了数组上相应的哈希值元素上)但当链表元素超过八个时,则会将链表变成红黑树来加快对元素操作。这就有较高的效率来面对海量数据。(原因是链表过长的话影响效率,链表查询很慢,增删快,但删除时他每次还是得一个一个的查询元素才能删除,当链表较长时就不如树有效率,所以当元素超过8个时,就将链表转为红黑树)这个原理是哈希表中的链地址法,可以说HashSet是通过哈希表实现的。LinkedHashSet:继承HashSet,但底层是通过LinkedHashMap来实现的,在HashSet的基础上并没有什么延申,还是HashSet的一些操作,但底层实现原理变了,底层是双向链表,这就使他变得有序,怎么存入就是怎么取出。TreeSet:和LinkedHashSet一样,是Set集合中有序的实现类。TreeSet的底层是通过TreeMap来实现的,键的类型为TreeSet的泛型类型,值为Object类型。TreeSet的主要作用是进行排序,由于底层原理使用到了树结构,其本身在存储时就对元素做了一些排序。当然排序的规则要规定,可以使泛型类型实现Comparable接口或者Comparator接口。如果是Comparable接口,则compareTo方法返回的是固定值0的话,集合只有一个元素,是固定值-1的话集合倒序存储,是固定值1的话集合按序存储,当然按元素比较结果排序时,则是按红黑树结构排序。

上一篇 下一篇

猜你喜欢

热点阅读