集合与异常处理

1.1包装数据类型 

        针对于基本数据类型实现的类类型转换。例如,一个int类型如果想要完成比如类似于数据类型转换,再比如完成获取到整型的最大值。在包装数据类型当中对以上的操作都提供对应的API。能够更加的面向对象设计。在java中一共有八种包装数据类型,都来自于java.lang包,提供了Boolean、Byte、Character、Double、Float、Integer、Logn、short。这里以Integer举例:

1.2 Integer

        1.2.1基本使用方式

//自动拆装箱

//自动装箱
Integer num = 25 ; //将一个int类型转换为Integer包装数据类型
num.xxx() ;

//自动拆箱
int num1 = num ;  // 将一个Integer类型转换为int类型

//Integer中提供了大量的静态方法,可以实现各种不同所需操作。
Integer num = Integer.valueOf(int num) ;
API:

        valueOf():实现将一个字符串(数值)或者是普通int类型转换为Integer包装类型。

public static Integer valueOf(String s)
                       throws NumberFormatException
                       
public static Integer valueOf(int i)

NumberFormatException:在进行数字格式化转换的过程中,如果无法转换就会抛出异常

         parseInt():将一个字符串转换为int类型。

public static int parseInt(String s)
                    throws NumberFormatException

 1.2.2Integer中的cache缓存

        在Integer类中,为了能够提高性能,所以采用了缓存的机制。在进行复制过程中。如果值得范围在-128~127之间,就会从缓存中直接返回对应的值,但如果超过了范围,就会从新构建一个Integer对象。

private final int value;

public Integer(int value) {
    this.value = value;
}

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer[] cache;  //缓存
    static {
    // high value may be configured by property
    int h = 127;
    String integerCacheHighPropValue =
        VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    if (integerCacheHighPropValue != null) {
        try {
            h = Math.max(parseInt(integerCacheHighPropValue), 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
        } catch( NumberFormatException nfe) {
            // If the property cannot be parsed into an int, ignore it.
        }
    }
    high = h;

    // Load IntegerCache.archivedCache from archive, if possible
    CDS.initializeFromArchive(IntegerCache.class);
    int size = (high - low) + 1;

    // Use the archived cache if it exists and is large enough
    if (archivedCache == null || size > archivedCache.length) {
        Integer[] c = new Integer[size];
        int j = low;
        for(int i = 0; i < c.length; i++) {
            c[i] = new Integer(j++);
        }
        archivedCache = c;
    }
    cache = archivedCache;
    // range [-128, 127] must be interned (JLS7 5.1.7)
    assert IntegerCache.high >= 127;
}



public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
int num = 20 ;

Integer num1 = 20 ;

num == num1   true

Integer num1 = 122 ;
Integer num2 = 122 ;

num1 == num2  //true

Integer num1 = 128 ;
Integer num2 = 128 ;

num1 == num2  //false

1.3Collection框架

Collection集合的特点是不唯一且无序。该集合接口是List与Set的父接口,为子类定义了大量的方法。该接口位于java.util包中。

        java集合框架提供了一套性能优良、使用方便的接口和类,他们位于java.util包中。Collections提供了对集合进行排序、遍历等多种算法实现。

        collection:接口存储一组不唯一,无序的对象。

        List:接口存储一组不唯一,有序(插入顺序)的对象

                ArrayList底层是动态数组,初始容量是0

                LinkedList底层为双向链表

        Set接口存储一组唯一,无序的对象

                HashSet利用散列表的形式,将对象存储在HashMap的key位置上。

                Treeset底层时红黑树。

        Map接口存储一组键值对象,提供key到value的映射

                HashMap是线程不安全的类,底层是哈希桶。

                TreeMap是线程安全的,底层为红黑树。

1.3.1 Collections

        Collections是集合中的一个工具类、提供了大量的静态方法,如addAll()、bianarySearch()、max()、mix()、copy()、synchronizedCollection(Collection<T> c)提供程序员的开发效率。

1.4List

        List集合继承了Collection接口。是一个线程不安全的集合类。能够存储null对象。其元素不唯一且有序。主要有ArrayList和LinkedList实现。是一个线程不安全的类。

        List接口常用方法:

        1.4.1ArrayList

                ArrayList实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高。能够存放任意Object类型,还能够自动扩容和缩放。

使用ArrayList数组:

List dogs = new ArrayList();
        ArrayList和数组之间的区别:

                数组:数据类型不可变。长度也不可发生改变,能够存放基本数据类型和引用数据类型。

                ArrayList:采用的是纯面向对象方式设计,底层应用是数组实现。只能够放置对象类型,即使放置的是基本数据类型,也会自动实现装箱过程。同时可以支持长度扩容和收缩。提供了大量的方法提供程序员使用,性能在固定大小以及数据类型场景下,性能不如数组。

        1.4.2LinkedList

                LinkedList底层是双向链表结构。

               LinkedList采用链表存储方式。插入、删除元素时效率比较高,并且允许所有元素(包括null)。除了实现List接口外,LinkedList类还为在列表的开头以及结尾add、get、remove和insert元素提供了统一的命名方法。

使用LinkedList数组:

LinkedList dogs = new LinkedList();

LinkedList的特殊方法:

1.5Set

        Set集合继承了Collection接口。是一个线程不安全的集合类。能够存储null对象。其存储元素唯一且无序,底层应用是HashMap的实例实现的。

        Set集合中的API方法和Collection父类接口基本一致:

1.5.1HashSet 

        HashSet,利用散列表的形式,将对象存储在HashMap的key位置上。元素唯一且无序。

 唯一性:如果在进行一个位置计算时,能够找到合适的位置(没有值),就会将值直接放进去,但是如果该位置有值,就会采用qeuals()方法和hashcode对位置上的内容进行比较。如果完全一致,就会直接覆盖。

用法:

Set<类型> set = new HashSet();
Dog dog1 = new Dog("花花","拉布拉多",20) ;
Dog dog2 = new Dog("草草","雪橇",40) ;
Dog dog3 = new Dog("树树","吉娃娃",50) ;
Dog dog4 = new Dog("木木","萨摩耶",80) ;
Dog dog5 = new Dog("水水","阿拉斯加",10) ;

set.add(dog1) ;
set.add(dog2) ;
set.add(dog3) ;
set.add(dog4) ;
set.add(dog5) ;
set.add(dog1) ;

//打印时会发现只有5只狗,由于dog1对象已经存在,所以set将后面的dog1对前面dog1对象进行了覆盖(equals、hashcode)。

1.5.2Iterator迭代器

        对Collection进行迭代的迭代器。Iterator接口,其中包含了hasNext()以及next()方法。可以判断是否还拥有下一个元素,如果还拥有下一个元素,可以通过next()获取对应元素。该迭代器只能作用在集合中。

Dog dog1 = new Dog("花花","拉布拉多",20) ;
Dog dog2 = new Dog("草草","雪橇",40) ;
Dog dog3 = new Dog("树树","吉娃娃",50) ;
Dog dog4 = new Dog("木木","萨摩耶",80) ;
Dog dog5 = new Dog("水水","阿拉斯加",10) ;

//ArrayList会出现重复对象
List<Dog> list =new ArrayList() ;
list.add(dog1);
list.add(dog2);
list.add(dog3);
list.add(dog4);
list.add(dog5);
list.add(dog2);

Iterator it = list.iterator() ;
while(it.hasNext()) {
    //输出或者进行类型转换
    System.out.println(it.next()) ;    
}

1.5.3一对多双向绑定

        代表类中两个类的关系表示。通常在一的一方放置一个集合属性,在多的一方放置一的一方的引用。这里用一个年纪有多个学生为例:

Grade类:

package com.csi.domain;

import java.util.Set;

public class Grade {

    //年级编号
    private int gradeNO ;

    //年级名称
    private String gradeName ;

    //年级备注
    private String gradeDesc ;

    //一对多关系映射:表示多个学生对象
    private Set<Student> studentSet ;

    public int getGradeNO() {
        return gradeNO;
    }

    public void setGradeNO(int gradeNO) {
        this.gradeNO = gradeNO;
    }

    public String getGradeName() {
        return gradeName;
    }

    public void setGradeName(String gradeName) {
        this.gradeName = gradeName;
    }

    public String getGradeDesc() {
        return gradeDesc;
    }

    public void setGradeDesc(String gradeDesc) {
        this.gradeDesc = gradeDesc;
    }

    public Set<Student> getStudentSet() {
        return studentSet;
    }

    public void setStudentSet(Set<Student> studentSet) {
        this.studentSet = studentSet;
    }
}

Student类:

package com.csi.domain;

public class Student {

    private String studentNO ;

    private String studentName ;

    private int age ;

    //建立一对一关系映射,表示一个学生对应一个年级
    private Grade grade ;

    public String getStudentNO() {
        return studentNO;
    }

    public void setStudentNO(String studentNO) {
        this.studentNO = studentNO;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }
}

测试:

package com.csi.test;

import com.csi.domain.Grade;
import com.csi.domain.Student;

import java.util.HashSet;
import java.util.Set;

public class TestGradeAndStudent {

    public static void main(String[] args) {

        /*实现类关系设计的双向绑定*/

        Grade grade = new Grade() ;
        grade.setGradeNO(1);
        grade.setGradeName("三年二班");
        grade.setGradeDesc("这是三年二班");

        /*********************************************/

        Student mzh = new Student() ;
        mzh.setStudentNO("100110");
        mzh.setStudentName("xxx");
        mzh.setAge(20);
        //一对一关系绑定
        mzh.setGrade(grade);

        Student cjx = new Student() ;
        cjx.setAge(21);
        cjx.setStudentName("xxx");
        cjx.setStudentNO("100119");
        cjx.setGrade(grade);

        Set<Student> set = new HashSet<>() ;
        set.add(mzh) ;
        set.add(cjx) ;

        /*****************************************/
        //建立一对多的关系
        grade.setStudentSet(set);

        System.out.println("年级名称:" + grade.getGradeName());

        System.out.println("该年级中包含了" + grade.getStudentSet().size() + "名学生");

        System.out.println("学生编号\t\t学生姓名\t\t所属年级");
        for(Student student: grade.getStudentSet()) {
            System.out.println(student.getStudentNO() +
                            "\t\t" + student.getStudentName() +
                            "\t\t" + student.getGrade().getGradeName());
        }


    }

}

1.5.4Treeset

        Treeset默认情况下能够对“基本数据类型”进行自然排序,但是功能更加倾斜于对于对象的排序。对象如果想要实现自定义排序的排序方式,则需要自定义类采用实现‘java.lang.comp’

1.6Map

Map接口存储一组键值对象,提供key(唯一)到value的映射。

Map实现:

Map countries = new HashMap();
countruies.put("CN","中华人民共和国");
countruies.put("US","美利坚和众国");

Map接口常用方法:

 1.6.1HashMap

        注意,此实现不是同步的。左侧的key是不能够重复的,右侧的值可以重复。基于哈希表的Map接口的实现。此实现提供所有可选的映射操作,并允许使用null值和null键。(除了非同步和允许使用null之外,HashMap类与Hashtable大致相同。)由于采用的是数组+链表+红黑树的结构,所以需要保障将key能够均匀分布在数组中,在过程当中,应用了key的hashcode值重新计算(高低位参与计算)结合位运算(数组长度-1&hashcode[该作用与hash值对数组长度取模一致]),此类不保证映射的顺序,特别是它不保证该顺序恒久不变【当数据量过多可能会出现集合扩容】

        此实现假定哈希函数将元素适当的分布在个桶之间,可为基本操作(get和put)提供稳定的性能。迭代collection视图所需的时间与HashMap实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置太高(或将加载因子设置的太低)。

        扩容点实在‘数组长度(1<<4  16)*负载因子(0.75)',负载因子0.75是一种通过大量的运算和实验所得到的最佳值,过大会造成空间不够使用,过小会造成空间浪费。

1.6.2遍历Map集合的方法:

方法1:通过迭代器Iterator实现遍历

        获取Iterator:Collection接口的iterator()方法

        Iterator的方法:boolean hasNext():判断是否存在另一个可访问的元素。Object next():返回要访问的下一个元素。

方法2:增强for循环

        

public static void main(String[] args) {
        Map<String, List<Goods>> map = new HashMap<>();

        Goods goods1 = new Goods("1001","洗衣机",2000);
        Goods goods2 = new Goods("1002","电视",3000);
        Goods goods3 = new Goods("1003","电脑",1000);
        Goods goods4 = new Goods("1004","手机",4000);

        List<Goods> list = new ArrayList<>();
        list.add(goods1);
        list.add(goods2);
        list.add(goods3);
        list.add(goods4);

        Goods goods11 = new Goods("1011","小米汽车",210000);
        Goods goods12 = new Goods("1012","奥迪汽车",230000);
        Goods goods13 = new Goods("1013","奔驰汽车",310000);
        Goods goods14 = new Goods("1014","宝马汽车",410000);

        List<Goods> list1 = new ArrayList<>();
        list1.add(goods11);
        list1.add(goods12);
        list1.add(goods13);
        list1.add(goods14);

        map.put("电子产品",list);
        map.put("汽车",list1);

        for (Map.Entry<String,List<Goods>> listEntry : map.entrySet()){
            System.out.println(listEntry.getKey());
            for (Goods list2 : listEntry.getValue()){
                System.out.println(list2.getGoodsNO()+"\t\t"+list2.getGoodsName()+"\t\t"+list2.getGoosPrice());
            }
        }

    }

1.7异常处理

        顶级父类是Throwable类,其中包括Error错误类,Exception异常类。Exception包括两类,一类是运行时异常,另一类是检测异常。所有错误都是Error的直接或间接子类。

        运行时异常和非运行时异常;RuntimeException的子类都是运行时异常,其他的都是非运行时异常。

        运行时异常:也称为非检测异常(unchecked Exception),这些异常在编译期不检测,程序可以选择处理,也可以不处理。如果不处理运行时会中断,但是编译没问题;

        非运行时异常:也称为检测异常(checked Exception),是必须进行处理的异常,如果不处理,将发生编译期错误;

1.7.1 try...catch...finally

      

try{
    //代码块:要包含的内容可能就会产生异常。
}catch(异常类型 e) {
    e.printStackTrace() ;
}catch(异常类型 e) {
    System.out.println(e.getMessage()) ;
}catch(Exception e) { //大的异常要放在后面。
    System.out.println(e) ;
    return ; //return永远都会最后执行。先会执行finally块。
}finally{
    //最终要执行的代码块。一般用作资源释放或者是关闭。
}

try{

}finally{

}

        当try块中代码抛出了异常对象后,异常处理机制就将这个对象的类型与try后的catch语句中的异常类型进行匹配,如果类型相同,或者抛出的是捕获的子类,就称为匹配成功,那么异常就被捕获,就允许catch块中的语句,否则,称为异常没有被捕获,程序将中断。

        如果try中有多行代码,有可能抛出多种类型异常,那么可以使用多个catch语句:

        注意:catch语句的异常类型必须从子类到父类的顺序,否则编译错误。

        如果希望不管什么情况,有一些代码都是必须被执行,那么就可以把这些代码写道finally块中,一般用于资源的清理和释放工作。如:关闭已打开的文件、删除临时文件, 释放数据库连接。

        try可以省略catch与finally连用,如果出现了异常,不会被捕获处理,而是会继续finally。 

1.7.2 throw与throws

        两个关键字都是用于抛出异常。throw作用在方法体内容,而throws是放置在方法声明中。throw可以和自定义异常以及系统异常一起使用。

        如果抛出的是运行时异常,那么调用者是不需要进行异常处理,将异常信息在运行过程中出现异常时,由JVM虚拟机进行处理。

public void show(int i) {
    if(i == 0) {
        throw new RuntimeException() ;
    }
}
//自定义异常
public class MyException extends Exception {
    public MyException() {
        super("2003:异常信息") ;
    }
    
    public MyException(String msg) {
        super(msg) ;
    }
    
    public MyException(Throwable th) {
        super(th) ;
    }
    
    public MyException(Throwable th,String message) {
        super(th,message) ;
    }
}

public class Person {
    //如果是一个普通异常继承,则必须抛出时在方法声明上也要同时配合抛出。
    public void show(int i) throws MyException {
        if(i == 0) {
            throw new MyException() ;
        }
    }
}

public static void main() {
    try{
        new Person.show() ;
    }catch(MyException e) {
        e.printStackTrace() ;
    }
}

1.7.3 如果存在了finally、return、exit方法、运行顺序:

在try中没有异常的情况下try、catch、finally的执行顺序try --- finally

如果rty中有异常,执行顺序是try---catch---finally

如果try中没有异常并且try中有return这时候正常执行顺序是try---finally---return

如果try中有异常并且try中有return这时候正常执行顺序是try---catch---finally---return

如果try中有异常,相应catch中有return,顺序是try---catch---finally---return

总之fianlly永远执行!!!!!!!!除非前边有System.exit(0)退出虚拟机。

当try中有异常时,在catch中如果加了System.exit(1)--->(退出虚拟机的方法)

  当try中没有异常时如果加了System.exit(1);--->(退出虚拟机的方法)

  System.exit(参数);

   参数: 0 或 1 都代表退出虚拟机

   0:正常退出

   1:非正常退出

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值