Java集合框架(JCF)

目录

前言

集合类

一. List**

LinkedList

ArrayList 和 LinkedList的差异

ArrayList 和 Vector

使用泛型类/方法

二. Set

HashSet 

三. Map**

HashMap

HashMap 和 Hashtable

四. Queue 

工具类

Collections

Arrays 

比较器


前言

集合是什么?

  • 把一堆数据集中合并在一起进行统一的操作。

框架是什么?

  • 为了解决某个问题,而预先设计的一系列具有继承或实现关系的类与接口。

Java Collection Framework(集合框架)

  • 解决集合操作问题而预先设计好的一系列类与接口。

整个集合框架分为两个部分:

1、装东西的容器 -- 集合类;

2、为容器提供算法的操作类 -- 工具类。

集合类

Collection接口 是整个集合框架的核心接口。

它衍生出集合框架的四大子接口(四种不同的容器)

1、List接口 (直接从Collection接口衍生)

2、Set接口 (同上)

3、Map接口 (间接从Collection接口衍生)

4、Queue接口(直接从Collection接口衍生)


一. List**

特点:

线性(有序)

通俗讲就是,放到List当中的元素是有顺序的,它最大的特点就是有下标

常用的List接口主要是两个类:ArrayList 和 LinkedList。

所有的List实现类都是实现的同一个List接口,所以它们的常用方法都是被直接定义在接口当中的,具有一致性。


ArrayList

底层用的就是数组

(1)产生List集合对象

        //父类(接口)的引用  指向   子类(实现类)的对象
        List lst=new ArrayList();

(2) 放入数据    

  //放数据
        lst.add("hello");
        lst.add((new Date()));
        lst.add(100); //放入的是 自动封箱封装的一个Integer对象
                      //按add的顺序进行存放  (线性特点)

(3)增加add()

        lst.add(2,"haha");

        lst.add(5,"haha");

  注意:

1.增加的位置如果有元素,该元素会被后移一位

2.增加的位置 前面 有空位置 会报错

(4)获取get()


       Object object=lst.get(1);//通过下标获取
       if (object instanceof  String str){
           System.out.println(str);
       }else {
          System.out.println("类型不一致");
       }

 (5)修改get()


       lst.set(0,"Java");//通过下标修改指定位置的元素
       System.out.println(lst.get(0));

  (6)删除remove()


        lst.remove("Java");//根据对象进行删除
        lst.remove(1);//根据下标进行删除
        lst.remove(Integer.valueOf(100));

如果List中全是数字,怎么按元素删除?

给remove方法  传入该数字的包装类对象
因为List 的两个方法,一个按int接受 下标 ;一个按object接受 对象
删除 整数元素 需要清楚 List里面存放的不是基本数据类型 而是它的包装类对象

   (7)获取元素的个数size()     

   System.out.println("List中有:"+lst.size()+"个");

    (8)List的遍历

        1.List有下标  所以可用 for循环遍历

 for(int i=0;i< lst.size();i++){
            System.out.println(lst.get(i));
        }

        2.集合框架特有的循环方式---- 迭代器 Iterator  (过于复杂)
         注意:
         (1)迭代器只能从头到尾访问
         (2)迭代过程中  不能改变集合容器当中的元素个数

//将集合中的所有元素 全部导入迭代器中
Iterator it=lst.iterator();//来自Collection接口  List/Set都有此方法
while (it.hasNext()){//获取当前迭代器中 有无元素  有返回true 没有返回false,结束循环
   Object  value=it.next();//从迭代器中 取出 当前元素
   System.out.println(value);
}

        3.for-each

         注意:
         (1)它是语法糖,编译之后,它还是会成为原始语法。
         (2)集合框架类的for-each 底层:编译以后是迭代器的语法 循环过程中  也不能改变集合容                    器当中的元素个数

 for(Object value:lst){
            System.out.println(value);
        }


 for ( 变量类型  变量名 : 数组名 ) {
                       需要执行的循环语句;
 }

LinkedList

底层实现没有使用数组,而是使用的链表结构

链表结构  采用的散列空间进行存放;

数组:

元素1|元素2|元素3...

双向链表:
              [null]元素1[引用2]               [引用2]元素3[引用4]     

                                [引用3]元素4[引用5]     

   [引用1]元素2[引用3]     

每个元素的后面有一个存放引用的空间,该空间的引用指向下一个元素;最后一个元素指向null

用这种方式来表示每个元素之间的顺序关系。

ArrayList 和 LinkedList的差异

查询元素时,ArrayList效果更高               (LinkedList要顺着链条逐个查找)

增加删除元素时,LinkedList效果更高      (直接打断链条就删了)


ArrayList 和 Vector

Vector虽然名字中没有List,但它也是List接口下的一个实现类,且它的底层也是用的数组的方式。

Vector是线程安全的;ArrayList是不安全的(性能更好

API文档中描述的它是同步的; 
同步是线程安全的实现手段之一,某个类的描述说它是同步的,那么就说明它是线程安全的。

使用泛型类/方法

在实际开发当中,我们发现,通常我们是不会把不同数据类型的元素 放到一个集合当中去的,就算要放也有一定的要求,比如:你不会把座椅板凳和学生对象放在一个大集合中,做统一的处理;通常都还是要进行归类。在这种情况下,操作装Object的集合就不是那么方便了,我们需要把取出来的元素进行判定,判定它到底是哪种类型,然后再进行类型转换,才能调用到这种类型的特有行为。非常不方便。因此,才有了泛型。

< >限制集合类内部允许装什么类型的元素

再去操作数据时,就只能操作这个类型的元素

 List<String>stringList=new ArrayList<String>();
        stringList.add("江小白");
        String str=stringList.get(0);
语法细节:
1.<>里 只能书写一个类型  因为先人只定义了一个E
2.<>里 不能写基本数据类型 因为在集合中所有类型都是对象  所以要写成对应的包装类类型
3. “钻石语法”  第二个<>里 可以不写类型

注意:

Java中的泛型是“假泛型”,也就是说Java中的泛型检查只是由编译器去检查,到运行期就不会检查了

泛型是函数式编程的语法特点

它跟形参与实参不同(只知道数据类型,不知道数据值,需要外部者传入)【数据参数化】

泛型连要操作什么样的类型都不知道,需要外部的使用者把这个数据类型传递进来【类型参数化

二. Set

特点:

元素不能重复;且不保证存放的顺序就是你放入的顺序。

HashSet 

Set集合的常用类通常都是HashSet

1.增加

最大特点就是不能放置重复元素

HashSet是如何判断两个元素是否重复的?

(1)HashSet先调用元素对象的hashcode方法,看两个元素的哈希值是否相等,如果不等那肯定是不同对象。

(2)如果相等,再根据两个元素对象的equals方法判断是否返回true,为ture则被认为是相同对象,不能重复添加,为false则可以添加。

hashcode 和 equals的关系?

hashcode是JVM用来判断两个对象在 物理位置上是否相等;

equals是用来判断两个对象在业务上是否相等;

常用类不用考虑重写,先人已经写好了

自定义类(由于先人不知道这些类的比较规则,所以需要我们去重写)

(1)通常在重写的时候,要求重写equals,也应该重写hashcode方法;

(2)在规范上,JVM要求equals方法返回true的两个对象,hashcode也应该是同一个值;

(3)而equals方法返回false的两个对象,hashcode也应该是不同的值.;

2、获取元素 -- Set集合没有提供

3、修改元素 -- Set集合没有提供

4、删除元素 -- remove() 只有根据对象进行删除,没有根据下标进行删除的方法; 根据对象进行删除的remove方法不支持泛型。

5、获取元素个数 -- size()

6、遍历 Set集合没有下标的概念,所以不支持普通for循环,只支持迭代器或for-each的语法。

通常我们只有在强调不能存放同一元素的这个场景中才会使用它。


三. Map**

特点:

所有元素以  键值对 的方式存放;key不能重复 。

 常用的实现类 HashMap,另外还有可能出现的是Hashtable、以及可操作性文件的Properties

HashMap

由于Map集合不是从Collection集合上直接继承而来的,所以它的方法自成一套:

(1)产生HashMap集合

   Map<String,StudentBean> stuMap = new HashMap<>();

(2)增加put

  stuMap.put("J192001",new StudentBean("zhang3",22));
        stuMap.put("J192002",new StudentBean("zhang4",21));
        stuMap.put("J192003",new StudentBean("zhang5",20));
        stuMap.put("J192004",new StudentBean("zhang6",18));

 (3)获取 get

   StudentBean stu0 = stuMap.get("J192003");
        System.out.println(stu0);

 通过键获取值,如果键不存在是直接返回null

(4)修改put

    stuMap.put("J192003",new StudentBean("zhang7",30));
        StudentBean stu1 = stuMap.get("J192003");
        System.out.println(stu1);

只需要保证传入的key是你需要修改的那个元素对应的key

(5)删除remove

  stuMap.remove("J192003");
        StudentBean stu2 = stuMap.get("J192003");
        System.out.println(stu2);

根据键去删除键值对儿,如果被删除的键不存在是不会报异常的

(6)获取元素个数 size

        System.out.println(stuMap.size());

(7)判断键或值是否存在 -- containsKey、containsValue

(8)遍历: 由于在Map当中每个元素是有key和value共同组成,所以通常要么遍历所有的key,要么遍历所有的value。

  • 获取所有的键 -- keySet

        得到一个Set集合,里面全部是这个Map中的键; 然后我们可以通过遍历这个Set从而得到所          有的键;

  • 获取所有的值 -- values

        得到一个Collection集合,里面全部是这个Map中的值。 然后我们可以通过遍历这个                        Collection从而得到所有的值。


HashMap 和 Hashtable

  • HashMap  是线程不安全的,可以用null做键或值
  • Hashtable  是线程安全的,不允许用null做键或值 

怎样遍历所有的键值对呢?

Map有一个方法entrySet(),该方法会 返回一个Set集合,集合里面每个元素又是一个Entry对象,Entry对象里面装了一个键和值

注意:

1、泛型的表达 Set<Map.Entry<String,UserBean>>

2、Entry是一个定义在Map内部的类型,这涉及到了内部类的语法。


四. Queue 

特点:

Queue 队列

先进先出 (可以理解为排队)

注意:

栈才是先进后出 (可以理解为 子弹上膛)

add() --- 放入成功返回true,放入失败(比如队列已满)则抛出异常

offer() ---失败直接返回false

element  ---返回第一个元素,如果没有就报异常

peek ---没有,返回null

remove ---返回首元素,并从队列中删除,没有首元素报异常

poll --- 没有,返null,不报异常

put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞

工具类

在集合框架中除了能够装东西的集合容器类以外,还给我们提供了工具类专门用来操作这些集合。

它们都是提供了一堆的静态方法,然后对传入的集合容器中的元素完成某个动作。

Collections

Collections操作的是集合框架中的容器类;主要是Collections及其下面的List、Set

Arrays 

Arrays 操作的是数组

比较器

自定义类要想使用Collections中的最大、最小以及sort排序等跟比较有关系的方法,那么要求自定义类必须实现比较器,然后在比较器中告知比较的规则。

比较器有两种:

1、Comparable接口 -- 内部比较器; 它是由参与比较的对象自身去实现的,相当于自带的;

2、Comparator接口 -- 外部比较器; 它是独立于比较对象之外,在参与比较操作的时候给出的外部规则。

注意:

1、如果在比较的时候,传入了外部比较器,那么内部比较器不起作用了;就算没有实现内部比较器,也可以按外部比较器来进行排序;

2、我们把最常用的比较规则写到内部比较器当中,把用得少的比较规则写入到外部比较器当中;

3、如果外部比较器只用一次,那么可以采用匿名内部类的方式实现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BroRiver

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值