容器

数组本身也是容器,是一个简单的线性序列,访问效率非常高。但是数组本身不够灵活,一开始就要定义数组的元素。

collection(集合/容器)

set无顺序不重复(hashSet),list有顺序可以重复(ArrayList,LinkedList)。

map 存放键值对。

泛型:贴标签,建立类型安全的集合,本质就是数据类型的参数化,告诉编译器在调用的时候必须传入参数类型。

List中的方法:addAll(Collection B):把B中所有的元素都加到A里面

removeAll(Collection B):移除本容器中和B容器中共有的元素。

retainAll(Collection B):移除A容器中AB容器中非交集的元素。

List:是有序的,可重复的容器。

有序:List中的每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制这些元素。

可重复:List允许加入重复的元素。更确切的讲,List通常允许满足e1.equals(e2)的元素重复加入容器。

List中常用的三种实现类:ArrayList、LinkedList和Vector。

ArrayList的底层实现是数组。

ArrayList中的add方法是一个重载的方法,可以在指定的位置插入一个数据。add(index,E);

remove(index):删除指定位置的元素。

set(index,E)将指定位置的数据设置为E,相当于修改替换。

get(index):获取索引地址的数据。

indexOf(Object o) 如果查到,返回索引第一次出现的位置,如果没有查到,返回-1。

lastIndexOf(Object o) 如果查到,返回索引最后一次出现的位置,如果没有查到,返回-1。

ArrayList

底层是数组的方式实现存储。特点是:查询效率高,增删效率低,线程不安全。我们一般使用它。

数组的长度是有限的,ArrayList是可以存放任意长度,底层自动扩容。定义一个更长的数组,老的复制到新的里面。默认长度是10,可以new ArrayList(size)来定义内部数组的长度。新长度等于老数组长度加老数组的一半

Old = Old+(Old>>1);

add与remove底层都是数组的拷贝,remove是自己拷贝自己,报后面的所有元素向前移动一个位置。

LinkedList

底层使用双向链表实现存储,特点是查询效率低,增删效率高,线程不安全。

双向链表也叫双链表,是链表的一种,没一个节点包含三部分,上一个节点、下一个节点、数据。

Vector

也是用数组实现的,但是相关方法都加了同步检查,因此“线程安全,效率低”。

建议:

需要多线程时用Vector

不存在线程安全的时候,查找多的用ArrayList,增删多的时候用LinkList。

 

Map

Map用来存储键值对,Map中存储的键值对是通过键来标识,所以键不能重复。如果重复,新的覆盖旧的。判断是否重复用的是Equals方法。

Map接口实现类有HashMap、TreeMap、HashTable、Properties等。

HashMap底层实现采用了哈希表,这是一种非常重要的数据结构。

哈希表的基本结构就是“数组+链表”。

数组:占用空间连续,寻址容易,查询速度快,但是增加删除的效率非常低。

链表:占用空间不连续。寻址困难,查询速度慢。但是增加和删除的效率非常高。

主要的存储结构是 Node(key value next hash),是一个单项列表。

每个节点Node 由key、value、next、hash四部分组成。

然后把节点放入Node[]数组中,数组中的每个元素都是一个链表。

 

 

hashMap的存储过程

1.先计算键对象的hashcode(),然后通过hash()算法计算出应该存储的位置【将hashcode与数组大小相除取余,余数就是节点存放的数组下标,后来改成了位运算,hashcode&(length-1)也是取余,但是长度必须是2的倍数。后来又进行了两次散列处理,是结果更加的散列。】

Jdk8中,当链表的长度大于8时,链表就转换为红黑树,增加了查询效率。

hashMap的取值过程

先计算键对象的hashcode,然后通过hash()算法算得hash值(node中的hash值)定位到存储的位置,然后通过Equals方法去找对应key进行比较,然后找到value从而找到准确的内容。

java规定:相同的对象的hashcode是相同的

扩容问题:hashMap数组桶的初始值是16,当元素达到数组桶的0.75倍时,将发生扩容,变成原来的2倍。扩容的本质是定义新的更大的数组,并将就数组内容挨个拷贝到新数组中。

JDK8将链表在大于8,数组总容量大于64 的情况下把链表变为红黑二叉树。
除了添加,其他效率都高了。

TreeMap

排序的情况下才使用TreeMap,TreeMap的底层是典型的红黑二叉树,每个节点都存储了本身数据、左节点、右节点、父节点、以及节点颜色。

遍历时按照key递增的方式进行排序。

Comparable接口

Comparable接口的方法中有一个compareTo方法 重写compareTo方法定义比较对象,返回值负数对应的是小于,正数是大于,0是等于。
class Emp  implements Comparable<Emp>  {
    int id;
    String name;
    double salary;
    
    public Emp(int id, String name, double salary) {
        super();
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return  "id:"+id+",name:"+name+",salary:"+salary;
    }
    
    @Override
    public int compareTo(Emp o) {        //负数:小于,0:等于,正数:大于
        
        if(this.salary>o.salary){
            return 1;
        }else if(this.salary<o.salary){
            return -1;
        }else{
            if(this.id>o.id){
                return 1;
            }else if(this.id<o.id){
                return -1;
            }else{
                return 0;
            }
        }
        
    }
    
}

HashMap与HashTable的区别

1、HashMap:线程不安全,效率高。允许key或value为null。

2、HashTable:线程安全,效率低。不允许key或value为null。

 

set接口

没有顺序,不可重复。只能遍历查找;不可重复指不允许加入重复的元素(新元素如果和Set中的某个元素通过equals()方法对比为true,则不能加入)。Set中只能放一个null元素,不能放入多个。

Set常见的实现类有:HashSet,TreeSet等,通产使用HashSet。

HashSet

HashSet也是采用的哈希算法实现的,底层实际用的是HashMap实现的(HashSet本质就是一个简化版的HashMap),因此,查询效率和增删效率都比较高。

HashSet就是一个hashMap,存储的值就是map的键,所以不能重复。

TreeSet

TreeSet的底层是TreeMap,也是用map的键进行set值的存储,也是按照元素递增的方式进行存储。自定义排序也用实现Comparable接口实现CompareTo方法。

Iterator迭代器

可遍历List Set Map

以hasNext和Next配合使用。

其中Map需要先用keySet获取键,然后迭代器遍历键的set获取值。或者使用entrySet直接获取Set<Entry<K,V>>然后进行遍历。

Collections工具类

对Set、List、Map进行排序、填充、查找元素的辅助方法。

void sort(List)对List容器内的元素进行排序,排序的规则是按照升序进行排序。自定义的类使用COmparable接口。

void shuffle(List) 随机排序 打乱顺序

void reverse(List)逆序排序 12345 --> 54321 132-->231

void fill(List,Object)用一个特定的对象重写整个List容器。

int binarySearch(List,Object)对于顺序的List容器,采用折半查找(二分法)的方法查找特定的对象。

原文地址:https://www.cnblogs.com/hg1205/p/12834789.html