美文网首页
Collection集合

Collection集合

作者: Finlay_Li | 来源:发表于2019-04-07 16:41 被阅读0次

定义

用于存储、操作任意类型对象的容器。
集合的底层是:数组

数组的弊端

  1. 声明数组后,长度固定不可变
  2. 没有提供查看有效元素个数的方法,容易导致空指针

集合的特点

  1. 集合的长度是可变的

底层是数组,初始长度为10
当存满时,java自动扩容50%,并以新容量创建新数组—>封装成集合

  1. 集合可以存储 任意类型的对象

如123 底层自动装箱。其实有了包装类。大多基本类型数据都可以存储了。

  1. 集合只能存储对象

Collection框架

java.util.Collection : 集合层级的根接口
1. |--java.util.List : 有序的,并且允许重复
List 体系集合都有索引值 元素按索引值有序存储,当然也就可以重复

image.png
  • |----ArrayList : 采用数组结构存储元素。

数组结构:
有索引
根据索引值对元素操作

因此:
查询操作多时,选择ArrayList存储数据,
因为可以根据索引值直接查询到所需的元素
若是增删则耗性能,在操作的索引位置开始,改变后面的元素索引

  • LinkedList :采用双向链表结构存储元素。

双向链表结构:
采用前向与后向索引维护
增删操作只需维护前后索引

因此:
增删操作多时,选择。添加或删除直接在两端操作即可。

  • Vector :线程安全的,古老的

2. java.util.Set : 无序的,并且不允许重复的

Set集合是通过hashCode()把hash值转换为索引值从而进行存储对象 而转换的索引值是不确定的,所以是无序的,并且可能存在重复转换的索引值。 所以不能重复存储 那么问题就来了: 1)怎么判断元素是否重复? 采用哈希算法 2)相同索引值而不重复元素怎么处理? 这种情况称为碰撞,通过单向链表处理

  • HashSet :是 Set 接口的典型实现类

采用数组(专业称为:Hash表)+单向链表结构存储元素
HashSet 判断元素是否重复的依据:采用哈希算法

  • LinkedHashSet :

相较于 HashSet 改为用链表维护元素的顺序。增删效率低于 HashSet
遍历效率高于 HashSet ,因他每个元素以链表维护,遍历时后面元素直接取出,不需再判断有没有

  • TreeSet :

采用二叉树结构
实现了Comparable接口,拥有排序

什么是哈希算法

当向Set中添加对象时,java会先调用此对象所在类的hashCode()方法将hashCode值转换为随机的索引值。

  1. 若此索引值位置没有对象存储,则此对象存储到此位置。
  2. 若此索引值位置已有对象存储,则通过equals()比较这两个对象内容是否相同
    若相同,视为重复不可再添加
    若不相同,则依靠单向链表存储。这种情况叫碰撞

TreeSet排序原理

  1. 其实现了Comparable接口,提供自然排序功能
    ComparTo()两个对象比较,返回int 1 -1 0,1代表大于,-1代表小于,0代表相等
  2. 当 TreeSet中存储元素是String、Interge类的对象时,内部已重写了ComparTo()。TreeSet会自动给排序
  3. 当TreeSet中存储元素是我们写的类,比如Person,那么TreeSet就不知道怎么排了,我们可以做定制排序,两种方式:

①自然排序(Comparable接口):
1)把添加到 TreeSet 集合中对象的类实现 Comparable 接口
2)重写 compareTo(Object o1) 方法

②定制排序(Comparator接口):
1)声明一个类实现 Comparator 接口
2)重写 compare(Object o1, Object o2) 方法
3)将该实现类的实例作为参数传递给 TreeSet 的构造器

Collection常用方法

  1. add(Object obj) : 添加元素到集合中

  2. size() : 获取集合中有效元素的个数

  3. clear() : 清空集合中所有元素

  4. isEmpty() : 判断集合中是否为空

  5. contains(Object obj)
    判断依据:根据对象所在的类的equals()方法进行判断
    注意:如存入集合中对象是自定义的,要求自定义类要重写equals()

  6. addAll(Collection c) : 将 c 集合中所有的元素添加到当前集合中

  7. containsAll(Collection c) : 判断 c 集合中所有的元素是否包含在当前集合中

  8. remove(Object o) : 删除集合中指定元素

  9. removeAll(Collection c) : 删除 c 集合中所有的元素

  10. retainAll(Collection c): 取交集

  11. toArray() : 将集合转换为数组
    12.hashCode()
    13.iterator() 迭代器

List常用方法

除了继承Collection,自己的方法有

  1. void add(int index, Object ele)
  2. boolean addAll(int index, Collection eles)
  3. Object get(int index) : 获取指定索引位置的元素
  4. int indexOf(Object obj):返回给定对象在list中的索引值
  5. int lastIndexOf(Object obj)
  6. Object remove(int index) : 删除指定索引位置的元素
  7. Object set(int index, Object ele) : 将指定索引位置的元素,替换成 ele
  8. List subList(int fromIndex, int toIndex):截取元素,包头不包尾

LinkedList常用方法

除了继承Collection,自己的方法有

  1. addFirst();
  2. addLast();
  3. getFirst();
  4. getLast();
  5. removeFirst();
  6. removeLast();

set常用方法

与Collection接口相同

集合的遍历

  1. 增强 for 循环

for(被遍历集合中元素的数据类型 变量名 : 被遍历的集合){

}


        for(Object obj : list){

            System.out.println(obj);

        }
  1. 使用 Iterator 迭代器
    迭代器接口为每个集合都提供迭代器,使用时以实例调用,java返回属于当前集合类的迭代器
        //①获取 当前 集合  的迭代器

        Iterator it = list.iterator();

        //②通过 hasNext() 与 next() 方法遍历集合元素

        while(it.hasNext()){

            Object obj = it.next();

            System.out.println(obj);

        }

注意1
通常一个 hasNext() 方法配合一个 next() 使用
因迭代器有标记指针,当it.hasNext()时,会判断下一个位置是否有元素
有则Object obj = it.next() 进行赋值
若两个next() 同时使用时,上一个指针位置赋值后未有操作,紧接着操作下一个
it.next(),即遍历漏了

注意2
hasNext():是否有更多元素
next():下一个元素

  1. 列表迭代器: ListIterator (是 List 集合特有的迭代器)
    @Test

    public void test2(){

        List list = new ArrayList();

        list.add("AA");

        list.add("BB");

        list.add("CC");

        list.add("DD");

        list.add("EE");

        //需求:判断若集合中元素为 "BB" , 在该元素位置添加一个 "bbb"

        ListIterator li = list.listIterator();

        while(li.hasNext()){

            Object obj = li.next();

            if(obj.equals("BB")){

                li.add("bbb");

            }

        }

        for (Object o : list) {

            System.out.println(o);

        }

    }

HashSet系列问题

  1. hashCode值转换索引值出现相同的原因?
    底层数组(哈希表)长度是固定的,hashCode值虽通过转换
    但得到的结果一定是存在长度的索引值。不然放哪。
    比如长度为5,那么转换的索引值必须是0,1,2,3,4

  2. 导致碰撞的发生?
    hashCode转换索引值出现相同,而对象的内容不同

  3. Set为什么可以发生碰撞?
    底层结构:数组(哈希码表)+ 单向链表
    当碰撞时,将依赖链表结构,把碰撞对象加在原对象之后

  4. 若HashSet底层数组长度存满后如何处理?
    不会出现存储满,因java通过判断,当数组存储到加载因子0.75时即以原数组*2进行自动扩容。
    扩容后,碰撞位置中的所有元素将重新转换。再分配存储!(jdk 1.7)
    碰撞是不可避免的,我们应尽量避免碰撞

  5. 为什么hashCode() 与 equals()要一并重写?
    若是无重写hashCode(),使用的还是Object类的hashCode(),得到不同的唯一hashCode值
    即使我们创建的实例内容相同,hashCode值亦不相同。那么再转换为索引值时,产生的索引值也不同
    那么,即使是重复的对象,也将直接存入。
    当重写hashCode()后,内容相同的实例得到的值必须一样。再转换为索引值时,他们的索引值也一样。

  6. hashCode() 与 equals()的重写?
    快捷生成即可。然后根据自己的需求修改

removeAll的巧用记录

public static void main(String[] args) {

    ArrayList<Integer> var1 = new ArrayList<>();

    ArrayList<Integer> var2 = new ArrayList<>();

    var1.add(1);

    var1.add(3);

    var1.add(4);

    var2.add(2);

    var1.add(2);

    var1.removeAll(var2);

    System.out.println(var1.toString());

    var2.add(4);

    var1.removeAll(var2);

    //是否还 == 原memberList?是的

    System.out.println(var1.toString());

}

循环内删除元素

java语言中,for循环有三种实现方法 :

1、for循环遍历list
2、增强for循环
3、iterator遍历

注意:只有第三种可以正确的在for循环中删除对应元素,否则会抛null指针
第一种方式,由于ArrayList底层使用数组方式实现,当删除其中某一元素时,其余数组下标会前移,导致继续进行删除时会略过下一元素,最终的结果也会异常

第二种方式,会抛出ConcurrentModificationException的错误,即并发修改异常,具体异常原因可参考《Java ConcurrentModificationException异常原因和解决方法》

使用迭代器(官方推荐)

Iterator<Integer> it = intList.iterator();
where(it.hasNext()){
    if(it.next() == 13){   //it.next()方法即可返回当前元素
        it.remove();
    }

要注意的是,必须使用iterator的remove方法,如果用list的remove方法同样会报上面提到的ConcurrentModificationException错误。

相关文章

  • Java基础之常用集合

    集合分为单列集合(Collection)和双列集合(Map),先说单列集合Collection Collecti...

  • JAVA基础---Collection集合 List

    ##一 Collection集合 ### 01 集合体系结构 a:Collection 集合(单身汉集合) ...

  • 哪些类继承了Collection接口

    Collection集合的基本结构: 1、Collection接口 Collection是最基本集合接口,它定义了...

  • 3/10day07_Collection_迭代器_泛型_数据结构

    今日内容 Collection集合 迭代器 泛型 数据结构 Collection集合[重点] 集合的介绍,集合和数...

  • 集合框架

    Collection Collection集合是单列集合的顶层接口。Collection表示一组对象,这些对象也称...

  • 用流收集数据

    Collection、Collector和Collect的区别: Collection:Collection是集合...

  • Java Collection集合

    Collection集合 collection集合作为List集合和Set集合共有的父类拥有着List集合和Set...

  • Java实战开发篇-8 集合

    集合 一、简介 1.集合分为Collection集合和List集合(1)Collection是集合类的一个接口,它...

  • JAVA基础(五)

    集合的由来? 集合和数组的区别? Collection集合的功能概述? Collection集合存储字符串并遍历?...

  • JJJJJava集合

    集合与数组的区别 Collection集合的方法 常用集合的分类 Collection 接口的接口 对象的集合(单...

网友评论

      本文标题:Collection集合

      本文链接:https://www.haomeiwen.com/subject/vppsiqtx.html