java集合

集合

概念

java中的集合就是用来替换掉定长数组的一个更高级的容器

和数组的区别

优点

1.长度不用在定义的时候就定死

2.一个集合可以存多种不同类型的数据

3.封装了多种对集合中的元素进行操作的方法

总体框架

java的集合总体分2种,一类是实现Collection接口;另一类是实现Map接口

Collection是单列集合,而Map是双列(key-value)集合

单列集合下的实现类分2种,Set(无序不重复)和List(有序可重复)

List

List 接口的实现类 ArrayList

是个动态数组,与普通的数组相比,ArrayList的大小是可变的,可以根据需要动态增长或缩小。

初始默认容量为10,容量不足的时候会自动扩容至1.5倍的大小

非线程安全

缺点:

由于ArrayList的底层是数组结构,所以ArrayList的查询效率高,可通过下标直接查询,

但是他的添加和删除效率低,原因是因为添加和删除操作要涉及到数据的迁移。

ArrayList的遍历
1.迭代器遍历

迭代器初始状态不指向任何元素

第一次使用next()方法后先移向第一个元素,然后获取到这个元素。

用next()方法前先用hasNext()方法判断是否有下一个元素,否则如果下一个位置没有元素时使用了next()方法就会报异常

迭代器遍历代码:

2.增强for遍历(常用)

增强for循环代码,在idea中用"集合名称.for"就能打出以下代码

ArrayList底层结构

1.ArrayList底层是用一个object类型的数组实现的

2.在定义时可在构造器里写集合的初始容量,这个容量就是底层数组的大小

3.如果没有填初始容量,那么初始时集合大小为0,当第一次使用add方法时数组大小变成10

4.当数组容量达到10,自动扩容1.5倍变成15

List 接口的实现类 Vector

与ArrayList除了扩容机制不同外,另一特点是线程安全

List 接口的实现类 LinkedList

底层是双向链表

每个节点(Node对象),里面维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终完成双向链表;

所以添加和删除元素的效率较高

Set

Set下的接口的共有特点:无序不重复

遍历方式与List一致,但是不能通过索引获取组内元素

Set接口的实现类HashSet

  1. 底层是数组+链表+红黑树
  2. HashSet实现了Set接口;
  3. 可以存放 null 值,但是只能有一个null;
  4. HashSet 不保证元素是有序的,取决于hash后,再确定索引的结果;
  5. 不能有重复元素 / 对象;
  6. 在Java8中,如果一条链表的元素个数达到 TREEIFY_THRESHOLD(默认是8),并且table大小>=MIN_TREEIFY_CAPACITY(默认是64),就会进行树化(红黑树);

放入元素时,先用集合内对象的hashCode()计算出该元素应该放在哪个位置,

如果这个位置没有元素就直接放入;

这个位置有元素就再调用对象的equals()方法比较该元素以及以该元素为头节点的链表里面的所有元素,如果有一个元素比较时返回了true,就不添加新元素。如果都为false就将新元素放在末尾。

如果集合中的类没有重写hashCode()和equals()方法,默认使用Object类的这2个方法,计算和比较的都是地址值

HashSet的子类LinkedHashSet

LinkedHashSet继承了HashSet,是HashSet的子类

与HashSet的区别是LinkedHashSet里面的元素有序且不重复

底层是用数组+双向链表

还是先用hashCode()方法算出索引,再使用equals()方法判断是否要插入

Map

概述

Map接口和Collection接口并列,Collection接口是单列,而Map接口是双列,用于保存具有映射关系的数据:Key - Value;

Key 和 Value 可以是任何引用类型的数据

Key不可以重复,Value可以重复

Map 的 Key 可以为 null,value 也可以为 null,但 key 为 null 只能有一个;

Key 和 Value 之间存在单向一对一关系,即通过指定的 Key 总能找到对应的 Value

但不能直接通过Value找到Key

当插入新数据时如果这个新数据的key在map中已经存在,那么这个新元素的value就会覆盖原有的value

map接口常用方法
  • put :添加
  • remove : 根据键删除映射关系
  • get : 根据键获取值
  • size : 获取元素个数
  • isEmpty : 判断个数是否为0
  • clear : 清除
  • containsKey : 查找键是否存在
Map的遍历
public static void main(String[] args) {
        Map map = new HashMap();
        map.put("小明","百草味");
        map.put("小龙","蒲公英");
        map.put("小马","西兰花");
        //第一种:先取出所有的Key,通过Key取出对应的value
        Set keySet = map.keySet();
        //增强for
        for(Object key : keySet){
            System.out.println(key+" - "+map.get(key));
        }
        //第二种:把所有的value取出
        Collection values = map.values();
        //然后遍历Collection就行
        //增强for
        for(Object value : values){
            System.out.println(value);
        }

        //第三种:通过EntrySet来获取
        Set entrySet = map.entrySet();
        //(1)增强for
        for(Object entry : entrySet){
            //将entry转成map.Entry
            Map.Entry m = (Map.Entry) entry;
            System.out.println(m.getKey()+" - "+m.getValue());
        }

    }
Map的实现类HashMap

HashMap 底层维护了 Node 类型的数组 table ,默认为 null;
当创建对象时,将加载因子(loadfactor)初始化为0.75;
当添加 key-value 时,通过 key 的哈希值得到在 table的索引,然后判断该索引处是否有元素,如果没有元素则直接添加。如果该索引处有元素,继续判断该元素的 key 是否和准备加入的 key 相等,如果相等,则直接替换 value;如果不相等,则需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。(扩容机制和HashSet完全一样,因为HashSet底层就是HashMap)
第一次添加,会扩容 table 容量为16,临界值(threshold)为12;
以后再扩容,会扩容 table 容量为原来的2倍,临界值为原来的2倍,即24,以此类推;
在Java8中,如果一条链表的元素个数超过 TREEIFY_THRESHOLD(默认是8),并且 table的大小>= MIN_CAPACITY(默认是64),就会进行树化(红黑树);

异常处理

概念

  程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常

Java程序在执行过程中所发生的异常事件可分为两类:

   Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError(栈溢出)和OOM(内存溢出)。一般不编写针对性的代码进行处理。
   Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:
            空指针访问
            试图读取不存在的文件
            网络连接中断
            数组越界

javac 是 Java 编译器的命令行工具,用于将 Java 源代码文件(以 .java 扩展名结尾)编译成 Java 字节码文件(以 .class 扩展名结尾)。Java 编译器将源代码转换为字节码,这些字节码可以在 Java 虚拟机(JVM)上运行。

检查异常

代码还没运行前,编译器就会检查你的代码,会不会出现异常,要求你对可能出现的异常必须做出相应的处理。

处理检查异常

1.通过throws Exception抛出,一直抛到java虚拟机来处理。

2.用try...catch捕获

检查异常类型

  除了RuntimeException与其子类,以及错误(Error),其他的都是检查异常

非检查异常

编译器不要求强制处置的异常,虽然你有可能出现错误,但是编译器不会在编译的时候检查

  对于这些异常,我们应该修正代码,而不是去通过异常处理器处理。这样的异常发生的原因多半是代码写的有问题。如除0错误ArithmeticException,错误的强制类型转换错误ClassCastException,数组索引越界ArrayIndexOutOfBoundsException,使用了空对象NullPointerException等等。

public class a7_AllDemo {
    public static void main(String[] args) {
        CMDCalculate();
    }
 
    public static void CMDCalculate() {
        Scanner scan = new Scanner(System.in);
        int num1 = scan.nextInt();
        int num2 = scan.nextInt();
        int result = devide(num1, num2);
        System.out.println("result:" + result);
        scan.close();
    }
 
    public static int devide(int num1, int num2) {
        return num1 / num2;
    }
}

常见异常


        java.lang.RuntimeException: 运行时异常
                ClassCastException: 类类型转换异常,当试图将对象强制转换为不是实例的子类时,抛出该异常;
                ArrayIndexOutOfBoundsException: 数组下标越界异常,当你使用不合法的索引访问数组时会抛出该异常;
                NullPointerException: 空指针异常,通过null进行方法和属性调用会抛出该异常;
                ArithmeticException: 算术运算异常,除数为0,抛出该异常;
                NumberFormatException: 数字转换异常,当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常;
                InputMismatchException: 输入不匹配异常,输入的值数据类型与设置的值数据类型不能匹配。

异常处理的处理机制

在编写程序时,经常要在可能出现错误的地方加上检测的代码,如进行x/y运算时,要检测分母为0,数据为空,输入的不是数据而是字符等。过多的if-else分支会导致程序的代码加长、臃肿,可读性差。将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁、并易于维护。因此采用异常处理机制。    

 在编写代码处理异常时,对于检查异常/非检查异常,都有2种不同的处理方式:
                1、使用try...catch...finally语句块处理它。
                2、在函数签名中使用throws 声明交给函数调用者去解决。

异常处理:try-catch-finally

    语法格式:
        try{
            ...... //可能产生异常的代码
        }
        catch( ExceptionName1 e ){
            ...... //当产生ExceptionName1型异常时的处置措施
        }
        catch( ExceptionName2 e ){
            ...... //当产生ExceptionName2型异常时的处置措施
        }
        finally{
            ...... //无论是否发生异常,都无条件执行的语句
        } 

finally主要做一些清理工作,如流的关闭,数据库连接的关闭等

异常处理:throws

 throws是另一种处理异常的方式,它不同于try...catch...finally,throws仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。

格式就是在方法后面加throws 异常类型1,异常类型2 . . .

  • 33
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值