Java教程

Java集合总结

本文主要是介绍Java集合总结,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

#### 1.1 ==null对象不可以调用方法==,会导致空指针异常NullPointerException

> eg:String str = null;            
>     str.equals("zs");

#### 1.2 创建LinkedList(双向链表)时,==有first(指向第一个节点)和last(调用完add之后指向最后添加的节点)==,①先创建新节点,存储值和赋值prev指向(上一个last节点),②再把上一个last节点的next指向当前last节点
##### prev element next

#### 1.3 ==Collection集合都可以用iterator来遍历数据,这也是toString和foreach的底层==

#### 1.3 集合包括Collection和Map(键值对);Collection(接口)集合包含List(接口)和Set(接口)集合
#### 1.3.1 List集合的实现类有ArrayList(动态数组)和LinkedList(双向链表),使用方法是一样的,遍历方式包括for循环、foreach、iterator;
#### 1.3.2 Set集合包括TreeSet(底层是TreeMap)和HashSet(HashMap),==Set集合只能先删再添加==,Set的遍历方式包括foreach、iterator;
#### 1.3.3 Map集合包括TreeMap(红黑树)和HahsMap(动态数组+链表+红黑树),==Map集合的Key只能先删除再添加,Value可以覆盖==,==Map的遍历方式只能通过①keySet()和②entrySet()方法转换为Set集合,再通过foreach、iterator来遍历输出==;
#### 1.3.4 对于==TreeXXX==**来说,底层是红黑树,在add()时就会排序,所以**==如果要存储自定义对象,需要①实现自然排序(Comparable)或者②传递比较器(Comparator)==;
#### 1.3.5 对于==HashXXX==**来说,底层是Hash表(动态数组+链表)+红黑树,在put()时会按hash值存储,所以**==如果要存储自定义对象,需要对Key对象①重写hashCode()和②equals()方法==;

#### 2.异常的处理,分为运行时异常(可处理可不处理)和检查时异常(必须处理)
> try:执行可能产生异常的代码                 
catch:捕获异常,并处理异常                 
finally:最终总会执行(除非JVM停止)                 
throw new :手动抛出异常                 
throws:声明异常          

```
try{
    //可能出现异常的代码
}catch(异常种类 变量名){
    //异常的处理代码
    //如e.printStack()  e.getMessage()
}finally{
    //无论是否异常都会执行,可以释放资源等
}
```

```
public class TestException3 {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        int result=0;
        try {
            System.out.println("请输入第一个数字");
            int num1=input.nextInt();//InputMismatchException
            System.out.println("请输入第二个数字");
            int num2=input.nextInt();
            result=num1/num2;//发生异常// ArethmicException
            //手动退出JVM
            //System.exit(0);
        }catch (Exception e) {//捕获 Exception:是所有异常的父类
            //处理
            //e.printStackTrace();
            System.out.println(e.getMessage());
        }finally {
            System.out.println("释放资源...");
        }
        System.out.println("结果是:"+result);
        System.out.println("程序结束了...");
    }
}
```

```
public void setAge(int age) {
        if(age>0&&age<=120) {
            this.age = age;
        }else {
            //抛出异常
            throw new RuntimeException("年龄不符合要求");
        }
    }
```

> 编写自定义异常
需继承Exception或Exception的子类,代表特定问题。


```
public AgeException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }
```

#### 3.常用类
##### 3.1 装箱拆箱(JDK1.5之后自动装箱拆箱)

==最大的作用是使得基本数据类型也可以作为对象进行一些行为,比如调用方法,作为对象参数,返回为对象==
> 装箱                             
1.构造方法 new Integer()                      
2.静态方法 valueOf()                            (推荐用静态方法,因为静态方法省资源,不用创建对象)           

> 拆箱                      
> 1.方法XXXvalue()                   
> 2.静态方法 parseXXX()                      

##### 3.2 Character(==字符的包装类,也算工具类==)
>  //isDigit   是否是数字               
//isLetter  是否是字母            
//isUpperCase  是否是大写字母              
//isLowerCase   是否是小写字母             
//isLetterOrDigit   是否是字母或者数字              

##### 3.3 Obeject类
==是所有类的父类或者间接父类,包含了hashCode()、equals()、toString()等方法,构造方法 public Object(){}==
> == 和 equals() 的区别                    
1.==是关系运算符,equals()是方法                     
2.==如果是引用类型是判断内存地址,equals()也是比较内存地址                     
3.当equals()重写之后,可以判断内容是否相等

==重写equals方法==

```
public class User {
    private String name;
    private int age;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //手动重写equals()方法,用来比较内容

    @Override
    public boolean equals(Object obj) {
        //判断内存地址是否相等
        if (this == obj) {
            return true;
        }

        //判断对象类型是否相等
        if (obj instanceof User) {
            User user = (User) obj;

            //判断内容是否相等
            if (this.getName().equals(user.getName())) {
                if (this.getAge() == user.getAge()) {
                    return true;
                }
            }
            return false;
        }

        return false;
    }
}
```

#### 4. String、StringBuffer、StringBuilder
> 1.String 是==不可变的字符序列==                 
> StringBuffer(线程安全)和StringBuilder(线程不安全)是==可变的字符序列==


```
String常用方法:
    charAt(int index)返回 char指定索引处的值。
    
    String concat(String str)将指定的字符串连接到该字符串的末尾。
    
    boolean contains(CharSequence s)当且仅当此字符串包含指定的char值序列时才返回true。boolean equals(Object anObject)将此字符串与指定对象进行比较。
    
    byte[] getBytes()使用平台的默认字符集将此 String编码为字节序列,将结果存储到新的字节数组中。
    
    int indexOf(int ch)返回指定字符第一次出现的字符串内的索引。
   
    boolean isEmpty()返回 true如果,且仅当 length()为 0 。
     
    int length()返回此字符串的长度。
        System.out.println(str.length());//16

    String replace(char oldChar, char newChar)返回从替换所有出现的导致一个字符串 oldChar在此字符串 newChar 。
     
    String[] split(String regex)将此字符串分割为给定的 regular expression的匹配。
        System.out.println(Arrays.toString(str.split("c")));//[ab, defghab, defghab, deab]

    String substring(int beginIndex)返回一个字符串,该字符串是此字符串的子字符串。
        System.out.println(str.substring(5));//fghabcdefghabcdeabc
      
    char[] toCharArray()将此字符串转换为新的字符数组。
        str = "AbCDefGh";
        System.out.println(Arrays.toString(str.toCharArray()));//[A, b, C, D, e, f, G, h]

    String toLowerCase()将所有在此字符 String使用默认语言环境的规则,以小写。
      

    String toUpperCase()将所有在此字符 String使用默认语言环境的规则大写。
    
    String trim()返回一个字符串,其值为此字符串,并删除任何前导和尾随空格。
        str = "   abcd  ef g h    ";
        System.out.println(str.trim());//"abcd  ef g h"
```


```
StringBuilder的常用方法:
    末尾追加 append()
        
    capacity()    返回当前容量
       
    charAt(int index)     返回 char在指定索引在这个序列值
       
    delete(int start, int end)    删除此序列的子字符串中的字符。
      
    StringBuilder insert(int offset, int i)   将第二个 int参数的字符串表示插入到此序列中。

    reverse() 反转
       
    截取    --  从开始索引截取到末尾索引
    substring(int start, int end)
        System.out.println(sb.substring(2, 6));//[start,end)
```

#### 5. Date类和SimpleDateFormat

```
    1.new Date()            格林威治时间               
    2.new Date(long date)   使用给定的毫秒时间值构造一个 Date对象。(要加时区小时时间,东八区+8小时)
```

```
public class Demo02 {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println("格林威治时间:" + date);//格林威治时间   Tue Nov 09 20:00:24 CST 2021

        //2021-11-09 20:00:00
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //调用方法格式化时间
        String timeStr = sdf.format(date);
        System.out.println("格式化时间:" + timeStr);

        //在1970年1月1日 00:00:00的基准时间上添加一个小时
        Date date1 = new Date(1000 * 60 * 60);
        String time1 = sdf.format(date1);
        System.out.println(time1);//东八区,+8小时
    }
}
```

#### 6. BigInteger和BigDecimal

> BigInteger:大长度的 int 类型包装类                 
> BigDecimal:精准运算的类,可小数运算,可大数运算

#### 7. System
> Syste.exit() 退出JVM,0表示正常退出,非0表示非正常退出          
> System.gc()  运行垃圾回收器

#### 8. 内部类
> 1.成员内部类(一般新建外部类,再通过外部类新建内部类)       
2.局部内部类(不可以有访问修饰符,只能在方法内使用,在内部类外面创建对象)                  
3.==静态内部类==(在外部通过外部类.内部类创建,类型为内部类,常用于底层代码,在底层代码中,有时用来作为对象类比如Node<E>)                   
4.==匿名内部类==(适用于创建之后只使用一次或者少次的情况)

```
public class Demo01 {
    public static void main(String[] args) {
        //静态内部类,通过外部类直接调用,但是内部类还是要new
        //Inner inner = Outer.new Inner();
        Outer.Inner inner = new Outer.Inner();
        inner.setId(10);
        System.out.println(inner.getId());
    }
}
```

```
public class Demo01 {
    public static void main(String[] args) {
        //匿名内部类,适用于创建之后使用一次或者少次的情况
        MyInterfaceImpl mii = new MyInterfaceImpl();
        mii.method();

        System.out.println("------多态---------");
        MyInterface mi = new MyInterfaceImpl();
        mi.method();

        System.out.println("-------匿名内部类-------");
        MyInterface mi2 = new MyInterface() {
            @Override
            public void method() {
                System.out.println("通过匿名内部类的方式实现了接口的method方法");
            }
        };

        mi2.method();
    }
}
```

#### 9. Collection集合(是接口)
##### ==++传入的参数都要是对象,因为基本数据类型有装箱类(自动装箱),所以万物皆对象++==
##### 9.1 List集合(是接口),==有序可重复==
> 1.==ArrayList:底层是动态数组==,初始化长度为0,当第一次添加时将长度改为10,每次要扩容1.5倍                
==LinkedList:底层是双向链表==,first指向第一个节点,last指向已存储的最后一个节点,理论长度无限长               
==Vector:元老级,底层是动态数组==,线程安全的集合,遍历方式和iterator有点相似    


```
    ArrayList和LinkedList方法相同,因为都实现了List类,
    只不过底层不一样,常用方法有:
        //添加    boolean     add(Object o)
        //修改    E           set(int index, E element)
        //删除    boolean     remove(@Nullable Object o)
        //查找    E           get(int index)
        //迭代器  Iterator<E> iterator()  
```
#####  ArrayList 和 LinkedList的异同
> 1.ArrayList 底层是动态数组,LinkedList 底层是双向链表
> 2.ArrayList 查询比 LinkedList 更快               
> 3.如果不需要扩容,ArrayList 末尾追加比 LinkedList 更快                       
> 4.修改对象 ArrayList 比 LinkedList 更快                  
> 5.中间插入和中间删除不同情况效率不一致           
> 6.ArrayList 长度有限,LinkedList 理论上长度无限

[![IsqXDg.png](https://z3.ax1x.com/2021/11/13/IsqXDg.png)](https://imgtu.com/i/IsqXDg)

[![IsLP2V.png](https://z3.ax1x.com/2021/11/13/IsLP2V.png)](https://imgtu.com/i/IsLP2V)

##### Vector类(很少用,但是实现了和ArrayList一样(存疑)的方法)
```
import java.util.Enumeration;
import java.util.Vector;

public class Demo02 {
    public static void main(String[] args) {
        //Vector
        Vector vector = new Vector();
        //
        vector.addElement("a");
        vector.addElement("b");
        vector.addElement("c");

        //Enumeration<E> elements()     返回此向量的组件的枚举。
        //相当于Vector的迭代器
        Enumeration elements = vector.elements();
        while (elements.hasMoreElements()) {
            System.out.println(elements.nextElement());
        }
    }
}
```

##### 9.2 栈(类)和队列(接口,实现类是LinkedList)
> ++**==栈和队列都是List的子类,所以也都能使用父类的方法,比如iterator()==**++

> Stack:栈,用完即删,后进先出(LIFO)             
> Queue:队列,用完即删,先进先出(FIFO)

```
Stack和Queue的常用方法:
                            Stack           Queue
    特点                   后进先出         先进先出
    类型                     类              接口
    底层                    动态数组        双向链表
    存储                  add()/push()       add()
    取栈顶/队首元素         peek()           peek()
    用删栈顶/队首元素       pop()            poll()
    是否为空                        isEmpty()         
    容量                    size()           size()
    (迭代器)         Collection集合都可以用,隐式存在输出中
```

##### 9.3 迭代器 iterator 调用方法
> Iterator<E> iterator() 以正确的顺序返回该列表中的元素的迭代器。            
> 调用.iterator()方法,返回一个迭代器,通过while(.hasNext())和.next()循环打印数据

```
    //iterator()
    Iterator it = ll.iterator();
    System.out.println("迭代器iterator遍历方式:");
    //hasNext()     next()
    while (it.hasNext()) {
        System.out.println(it.next());
    }
```

##### 9.4 Set集合(是接口),==无序不可重复==

> 1.TreeSet:无序可排序,不可重复(有比较才不重复),不能存储null                       
**++==要实现“不可重复”,底层调用了TreeMap的put()方法,需要①实现自然排序或者②传递比较器==++**

> 2.HashSet:无序不可重复,可以存储null,在索引为0的位置(不一定是开头)                   
++**==要实现“不可重复”,底层调用了HashMap的put()方法,需要重写hashCode()方法和equals()方法==**++


```
    自然排序:
        存储进 TreeSet 集合的对象类必须实现 Comparable 接口,重写 compareTo(),
        在 compareTo()里制定排序规则,返回正数存储的对象往右子树方向,
        返回负数存储的对象往左子树方向,返回0则不存储

    比较器:
        在创建 TreeSet 集合对象的时候,传递 Comparator 接口的实现类对象,
        重写 Comparator 接口的 compare() ,在 compare() 里制定排序规则


    自然排序 vs 比较器
        1.使用自然排序需要改变存储对象类的结构
        2.使用比较器会额外添加多一个类
        3.当比较器与自然排序共存的时候,使用比较器进行排序
```

```
public class Demo01 {
    public static void main(String[] args) {
        TreeSet<User> set = new TreeSet<>(new Comparator<User>() {
            //以 age 从小到大排序,如果 age 相同以 id 从大到小排序
            @Override
            public int compare(User user1, User user2) {
                if(user1.getAge() != user2.getAge()){
                    return user1.getAge() - user2.getAge();
                }
                return user2.getId() - user1.getId();
            }
        });
        set.add(new User(1,"zs",18));
        set.add(new User(6,"ls",20));
        set.add(new User(3,"ww",16));
        set.add(new User(2,"z6",18));
        set.add(new User(5,"t7",39));
        set.add(new User(4,"w8",18));
        set.forEach(item -> System.out.println(item));
    }
}
```

[![IsLm5R.jpg](https://z3.ax1x.com/2021/11/13/IsLm5R.jpg)](https://imgtu.com/i/IsLm5R)

[![IsLK8x.jpg](https://z3.ax1x.com/2021/11/13/IsLK8x.jpg)](https://imgtu.com/i/IsLK8x)

#### 10. Map接口(k-v 键值对)
##### 10.1 TreeMap 无序可排序
> 对key进行排序,key不可重复;value可以重复,可以为null

> 存储自定义对象时,要①实现自然排序(Comparable)或者②传递比较器(Comparator)

```
public class Demo02 {
    public static void main(String[] args) {
        TreeMap<User, String> map = new TreeMap<>(new Comparator<User>() {
            @Override
            public int compare(User user1, User user2) {
                return user2.getId() - user1.getId();
            }
        });
        map.put(new User(1),"zs");
        map.put(new User(3),"ls");
        map.put(new User(2),"ww");
        map.put(new User(1),"zs");
        //按照id从大到小排序
        System.out.println(map);
        //两种遍历的方式
        //1.keySet
        Set<User> set1 = map.keySet();
        Iterator<User> it1 = set1.iterator();
        while (it1.hasNext()){
            System.out.println(it1.next());
        }

        //2.EntrySet
        Set<Map.Entry<User, String>> set2 = map.entrySet();
        Iterator<Map.Entry<User, String>> it2 = set2.iterator();
        while (it2.hasNext()){
            Map.Entry<User, String> entry = it2.next();
            User key = entry.getKey();
            String value = entry.getValue();
            System.out.println("Key:"+key+"Value:"+value);
        }
    }
}
```
##### 10.2 HashMap
> 底层是hash表(动态数组+链表)+红黑树,无序,key不可重复,value可以重复

> 存储自定义对象时,要重写Key对象的①hashCode()和equals()方法

```
public class Demo02 {
    public static void main(String[] args) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put(new Person(1),new User(1));
        map.put(new Person(2),new User(2));
        map.put(new Person(1),new User(2));
        map.put(new Person(2),new User(1));
        map.put(new Person(1),new User(1));
        System.out.println(map);
    }
}
```

```
public class Person {
    private int id;

    public Person(int id) {
        this.id = id;
    }

    public Person() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return id == person.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                '}';
    }
}
```

这篇关于Java集合总结的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!