0
点赞
收藏
分享

微信扫一扫

Java学习第八章(一)

豆丁趣 2022-03-18 阅读 76

视频链接:https://www.bilibili.com/video/BV1Rx411876f?p=1

视频范围P660 - P693

目录描述

1.集合概述

  1. 数组其实就是一个集合
  2. 集合实际上就是一个容器,是一个载体,可以来容纳其它类型的数据(可以一次容纳多个对象)
    举例在实际开发中,假设连接数据库,数据库当中有10条记录,那么假设把这10条记录查询出来,在java程序中会将10条数据封装成10个java对象,然后将10个java对象放到某一个集合当中,将集合传到前端,然后遍历集合,将一个数据一个数据展现出来。
  3. 集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,集合当中存储的都是java对象的内存地址(或者说集合中存储的是引用)
list.add(100);//自动装箱Integer
//注意:集合在java中本身是一个容器,是一个对象
//集合中任何时候存储的都是“引用”

在这里插入图片描述
4. 在java中每一个不同的集合,底层会对应不同的数据结构。往不同的集合中存储元素,等于将数据放到了不同的数据结构(数据存储的结构)当中。
注意:不同的数据结构,数据存储的方式不同,例如:数组、二叉树、链表、哈希表等等

//使用不同的集合等于使用了不同的数据结构
new ArrayList();//创建一个集合,底层是数组
new LinkedList();//创建一个集合,底层是链表
new TreeSet();//创建一个集合,底层是二叉树
  1. 集合在java JDK中java.util.;包下【所有的集合类和集合接口都在java.util.;包下】
  2. java中集合分为两大类:
集合备注
单个方式存储元素这一类集合中超级父接口: java.util.Collection;
以键值对的方式存储元素这一类集合中超级父接口: java.util.Map;
  1. 集合的继承结构图
    在这里插入图片描述
    在这里插入图片描述
  2. Map集合的继承结构图
    在这里插入图片描述
  3. 总结
实现类备注
ArrayList底层是数组
LinkedList底层是双向链表
Vector底层是数组,线程安全的,效率较低,使用较少
HashSet底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合key部分了
TreeSet底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合key部分了
HashMap底层是哈希表
Hashtable底层也是哈希表,只不过线程安全的,效率较低,使用较少
Properties是线程安全的,并且key和value只能存储字符串String
TreeMap底层是二叉树,TreeMap集合的key可以自动按照大小顺序排序

List集合存储元素的特点

  • 有序可重复
  • 有序:存进去的顺序和取出的顺序相同,每一个元素都有下标
  • 可重复:存进去1,可以再存储一个1

Set(Map)集合存储元素的特点

  • 无序不可重复
  • 无序:存进去的顺序和取出的顺序不一定相同,另外Set集合中元素没有下标
  • 不可重复:存进去1,不能再存储1了

SortedSet(SortedMap)集合存储元素特点

  • 首先是无序不可重复的,但是SortedSet集合中的元素是可排序的
  • 无序:存进去的顺序和取出的顺序不一定相同,另外Set集合中元素没有下标
  • 不可重复,存进去1,不能再存储1了
  • 可排序:可以按照大小顺序排列

注意: Map集合的key,就是一个Set集合,往Set集合中放数据,实际上放到了Map集合的key部分

2.Collection和terator

2.1 Collection接口中常用的方法

  1. 没有使用“泛型”之前Collection中可以存储Object的所有子类型
  2. 使用“泛型”之后Collection中只能存储O某个具体的类型
方法作用
boolean add(Object e)向集合中添加元素
int size()获取集合中元素的个数
void clear()清空集合
boolean contains(Object o)判断当前集合中是否包含元素o,包含返回true,不包含返回false
boolean remove(Object o)删除集合中的某个元素
boolean isEmpty()判断该集合中元素的个数是否为0
Object[ ] toArray()把集合转换为数组
package Collectice;

import java.util.ArrayList;
import java.util.Collection;

public class CollecticeTest01 {
    public static void main(String[] args) {

        //创建一个集合对象
        //Collection c = new Collection;//接口是抽象的,无法实例化

        //多态
        Collection c = new ArrayList();

        //测试Collection接口中的常用方法
        c.add(1200);//自动装箱(java5的新特性),实际上是放进去了一个对象的内存地址
                    //如:Integer x = new Integer(1200);
        c.add(3.14);//自动装箱
        c.add(new Object());
        c.add(new Student());
        c.add(true);//自动装箱


        //获取集合中元素的个数
        System.out.println("集合中元素个数是:" + c.size());//输出为:集合中元素个数是:5

        //清空集合
        c.clear();
        System.out.println("集合中元素个数是:" + c.size());//输出为:集合中元素个数是:0

        //再向集合中添加元素
        c.add("hello");
        c.add("world");
        c.add("浩克");
        c.add("绿巨人");

        //判断集合中是否包含 绿巨人
        boolean flag = c.contains("绿巨人");
        System.out.println(flag);//输出为:true


        //删除集合中某个元素
        c.remove("绿巨人");
        System.out.println("集合中元素个数是:" + c.size());//输出为:集合中元素个数是:3

        //判断集合中是否为空(集合中是否存在元素)
        System.out.println(c.isEmpty());//输出为:false

        //转换成数组

        Object[] objs = c.toArray();
        for (int i = 0; i < objs.length; i++) {
            
            //遍历数组
            Object o = objs[i];
            System.out.println(o);
        }
    }
}

class  Student{

}

2.2 集合遍历/迭代专题一

以下讲解的遍历方式/迭代方式,是所有Collection通用的一种方式,在Map集合中不能用,在所有的Collection以及子类中使用

package Collectice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollecticeTest02 {
    public static void main(String[] args) {

        //创建集合对象
        //后面的集合无所谓,主要看前面的Collection接口,怎么遍历/迭代
        Collection c = new ArrayList(); 

        //添加元素
        c.add("abc");
        c.add("def");
        c.add(100);
        c.add(new Object());

        //对集合Collection遍历/迭代

        //第一步:获取集合对象的迭代器对象Iterator
        Iterator it = c.iterator();


        //第二步:通过以上获取的迭代器对象开始迭代/遍历集合
        /*
        以下两个方法是迭代器对Iterator中的方法:
        boolean hasNext()如果仍有元素可以迭代,则返回true
        Object next()返回迭代的下一个元素
         */
        while (it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

运行结果

在这里插入图片描述
内存分析图

在这里插入图片描述

2.3 集合遍历/迭代专题二

package Collectice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class CollecticeTest03 {
    public static void main(String[] args) {

        //创建集合对象
        Collection c1 = new ArrayList();//ArrayList集合:有序可重复

        //添加元素
        c1.add(1);
        c1.add(2);
        c1.add(3);
        c1.add(4);
        c1.add(5);

        //迭代集合
        Iterator it = c1.iterator();

        while (it.hasNext()){

            //存进去是什么类型,取出来还是什么类型
            Object obj = it.next();

            if(obj instanceof Integer){
                System.out.println("Integer类型");
            }

            //只不过在输出的时候会转换成字符串,因为这里的println会调用toString()方法
            System.out.println(obj);
        }


        //HashSet集合:无序不可重复
        //无序:存进去和取出的顺序不一定相同
        //不可重复:存储100,不能再存储100
        Collection c2 = new HashSet();

        c2.add(100);
        c2.add(200);
        c2.add(300);
        c2.add(100);

        Iterator it2 = c2.iterator();
        while (it2.hasNext()){
            System.out.println(it2.next());
        }
    }
}

运行结果

在这里插入图片描述

2.4 contains方法解析

boolean contains(Object o) :判断当前集合中是否包含元素o,包含返回true,不包含返回false

contains方法是用来判断集合中是否包含某个元素的方法,底层判断集合中是否包含某个元素:

  1. 调用equals方法进行比对;
  2. equals方法返回true,就表示包含这个元素

,代码实例一

package Collectice;

import java.util.ArrayList;
import java.util.Collection;

public class CollecticeTest04 {
    public static void main(String[] args) {

        //创建集合对象
        Collection c = new ArrayList();

        //向集合中存储元素
        String s1 = new String("abc");
        c.add(s1);

        String s2 = new String("def");
        c.add(s2);

        //集合中元素的个数
        System.out.println("元素的个数为:" + c.size());//输出为:元素的个数为:2

        //新建的对象String
        String x = new String("abc");

        //c集合中是否x?
        System.out.println(c.contains(x));//输出为:true

    }
}

内存分析图

在这里插入图片描述
,代码实例二
存放在一个集合中的类型,一定要重写equals方法

package Collectice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;

public class CollecticeTest05 {
    public static void main(String[] args) {

        //创建集合对象
        Collection c = new ArrayList();

        //创建用户对象
        User u1 = new User("jack");
        //加入集合
        c.add(u1);

        //判断集合中是否包含u2
        User u2 = new User("jack");

        //没有重写equals之前:这个结果是false
        //System.out.println(c.contains(u2));//输出为:false

        //重写equals之后:这个结果是true
        System.out.println(c.contains(u2));//输出为:true
    }
}

class User{
    private String name;

    public User() {
    }

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

    //重写equals方法
    //将来调用equals方法的时候,一定是调用这个重写的equals方法
    public boolean equals(Object o) {
        if (o == null || !(o instanceof User)) return  false;
        if (o == this) return true;
        User u = (User)o;

        //如果名字一样表示同一个人(不再比较对象的内存地址了,比较内容)
        return u.name.equals(this.name);
    }
}

2.5 remove方法解析

代码实例一

package Collectice;

import java.util.ArrayList;
import java.util.Collection;

public class CollecticeTest06 {
    public static void main(String[] args) {

        //创建集合对象
        Collection cc = new ArrayList();

        //创建字符串对象
        String s1 = new String("hello");

        //加进去
        cc.add(s1);

        //创建一个新的字符串对象
        String s2 = new String("hello");

        //删除s2
        cc.remove(s2);

        //集合中元素个数
        System.out.println(cc.size());//输出为:0
    }
}

代码实例二

package Collectice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollecticeTest07 {
    public static void main(String[] args) {

        //创建集合
        Collection c = new ArrayList();

        //添加元素
        c.add(1); //Integer类型
        c.add(2);
        c.add(3);

        //获取迭代器
        Iterator it = c.iterator();

        while (it.hasNext()){
            //编写代码时next()方法返回值类型必须是object
            Object obj = it.next();
            System.out.println(obj);
        }

    }
}

运行结果

在这里插入图片描述
代码实例三
重点:当集合的结构发生改变时,迭代器必须重新获取,如果还是用以前老的迭代器,会出现异常:java.util.ConcurrentModificationException

package Collectice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollecticeTest07 {
    public static void main(String[] args) {

        //创建集合
        Collection c = new ArrayList();


        //注意:此时获取的迭代器,指向的是那是集合中没有元素状态下的迭代器
        //一定要注意:集合结构只要发生改变,迭代器必须重新获取
        //当集合结构发生了改变,迭代器没有重新获取时
        //调用next()方法时:java.util.ConcurrentModificationException
        Iterator it = c.iterator();


        //添加元素
        c.add(1); //Integer类型
        c.add(2);
        c.add(3);

        //获取迭代器
        //Iterator it = c.iterator();

        while (it.hasNext()){
            //编写代码时next()方法返回值类型必须是object
            Object obj = it.next();
            System.out.println(obj);
        }

    }
}

运行结果

在这里插入图片描述
代码实例四
重点:在迭代集合元素的过程中,不能调用集合对象的remove方法,删除元素会出现:java.util.ConcurrentModificationException

package Collectice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollecticeTest07 {
    public static void main(String[] args) {

        //创建集合
        Collection c = new ArrayList();

        //添加元素
        c.add(1); //Integer类型
        c.add(2);
        c.add(3);

        //获取迭代器
        Iterator it = c.iterator();

        while (it.hasNext()){
            Object obj = it.next();

            //删除元素
            //删除元素之后,集合的结构发生了变化,应该重新去获取迭代器
            //但是,循环下一次的时候并没有重新获取迭代器
            //所以会出现异常:java.util.ConcurrentModificationException
            //出异常根本原因:集合中元素删除了,但是没有更新迭代器(迭代器不知道集合变化了)
            //直接通过集合去删除元素,没有通知迭代器(导致迭代器的快照和原集合快照不同)
            c.remove(obj);
            System.out.println(obj);
        }

    }
}

运行结果

在这里插入图片描述
代码实例五
重点:在迭代元素的过程当中,一定要使用迭代器Iterator的remove方法,删除元素,不要使用集合自带的remove方法删除元素

package Collectice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollecticeTest07 {
    public static void main(String[] args) {

        //创建集合
        Collection c = new ArrayList();

        //添加元素
        c.add(1); //Integer类型
        c.add(2);
        c.add(3);

        //获取迭代器
        Iterator it = c.iterator();

        while (it.hasNext()){
            Object obj = it.next();

            //使用迭代器删除,删除的一定是迭代器指向的当前元素
            //迭代器去删除时,会自动更新迭代器,并且更新集合(删除集合中的元素)
            it.remove();
            System.out.println(obj);
        }
        System.out.println(c.size());//输出为:0
    }
}

运行结果

在这里插入图片描述

3.List接口

3.1 List接口方法

  1. List集合存储元素特点:有序可重复
    有序:List集合中的元素有下标。从0开始,以1递增
    可重复:存储一个1,还可以再存储1
  2. List接口自己特色方法:
特色方法
void add(int index,Object element)
Object get(int index)
int indexOf(Object o)
int LastIndexOf(Object o)
Object remove(int index)
Object set(int index ,Object element)

3.1.1 void add(int index,Object element)

这个方法使用不多,因为对于ArrayList集合来说效率比较低

package Collectice;

import java.util.*;

public class ListTest01 {
    public static void main(String[] args) {

        //创建list类型的集合
        //List mylist = new LinkedList();
        //List mylist = new Vector();
        List mylist = new ArrayList();

        //添加元素
        mylist.add("A");//默认都向集合末尾添加元素
        mylist.add("B");
        mylist.add("C");
        mylist.add("D");
        //在列表的指定位置插入指定元素(第一个参数是下标)
        //这个方法使用不多,因为对于ArrayList集合来说效率比较低
        mylist.add(1,"king");

        //迭代
        Iterator it = mylist.iterator();

        while (it.hasNext()){
            System.out.println(it.next());
        }

    }
}

3.1.2 Object get(int index)

根据下标获取元素

package Collectice;

import java.util.*;

public class ListTest01 {
    public static void main(String[] args) {

        //创建list类型的集合
        //List mylist = new LinkedList();
        //List mylist = new Vector();
        List mylist = new ArrayList();

        //添加元素
        mylist.add("A");
        mylist.add("B");
        mylist.add("C");
        mylist.add("D");

        //根据下标获取元素
        Object firstObj = mylist.get(0);
        System.out.println(firstObj);//输出为:A

        //因为有下标,所以list集合有自己比较特殊的遍历方法
        //通过下标遍历【list集合特有的方式,Set没有】
        for (int i = 0; i < mylist.size(); i++) {
            Object obj = mylist.get(i);
            System.out.println(obj);
        }

    }
}

3.1.3 int indexOf(Object o)

获取指定对象第一次出现处的索引

package Collectice;

import java.util.*;

public class ListTest01 {
    public static void main(String[] args) {

        //创建list类型的集合
        //List mylist = new LinkedList();
        //List mylist = new Vector();
        List mylist = new ArrayList();

        //添加元素
        mylist.add("A");
        mylist.add("B");
        mylist.add("C");
        mylist.add("D");

        //获取指定对象第一次出现处的索引
        System.out.println(mylist.indexOf("B"));//输出为:1

    }
}

3.1.4 int LastIndexOf(Object o)

获取指定对象最后一次出现处的索引

package Collectice;

import java.util.*;

public class ListTest01 {
    public static void main(String[] args) {

        //创建list类型的集合
        //List mylist = new LinkedList();
        //List mylist = new Vector();
        List mylist = new ArrayList();

        //添加元素
        mylist.add("A");
        mylist.add("B");
        mylist.add("C");
        mylist.add("C");
        mylist.add("D");

        //获取指定对象最后一次出现处的索引
        System.out.println(mylist.lastIndexOf("C"));//输出为:3

    }
}

3.1.5 Object remove(int index)

删除指定下标位置的元素

package Collectice;

import java.util.*;

public class ListTest01 {
    public static void main(String[] args) {

        //创建list类型的集合
        //List mylist = new LinkedList();
        //List mylist = new Vector();
        List mylist = new ArrayList();

        //添加元素
        mylist.add("A");
        mylist.add("B");
        mylist.add("C");
        mylist.add("D");

        //删除指定下标位置的元素
        //删除下标为0的元素
        mylist.remove(0);
        System.out.println(mylist.get(0));//输出为:B

    }
}

3.1.6 Object set(int index ,Object element)

package Collectice;

import java.util.*;

public class ListTest01 {
    public static void main(String[] args) {

        //创建list类型的集合
        //List mylist = new LinkedList();
        //List mylist = new Vector();
        List mylist = new ArrayList();

        //添加元素
        mylist.add("A");
        mylist.add("B");
        mylist.add("C");
        mylist.add("D");

        //修改指定位置的元素
        mylist.set(0,"F");
        System.out.println(mylist.get(0));//输出为:F
    }
}

3.2 ArrayList

  1. ArrayList集合初始化容量是10【底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量10】
  2. ArrayList集合底层是Obeject类型的数组Object[ ]
  3. 构造方法:new ArrayList()或者new ArrayList(20)
package Collectice;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest01 {
    public static void main(String[] args) {

        //默认初始化容量是10
        //数组的长度是10
        List list1 = new ArrayList();
        //集合的size()方法是获取当前集合中元素的个数,不是获取集合的容量
        System.out.println(list1.size());//输出为:0

        //默认初始化容量是20
        //数组的长度是20
        List list2 = new ArrayList(20);
        System.out.println(list2.size());//输出为:0
    }
}
  1. ArrayList集合的扩容:增长到原容量的1.5倍
    ArrayList集合底层是数组
    优化方式:尽可能少的扩容,因为数组扩容效率比较低,建议在使用ArrayList集合的时候预估计元素的个数,给定一个初始化容量
  2. 数组优点:检索效率比较高【每个元素占用空间大小相同,内存地址是连续的,知道首元素内存地址,然后知道下标,通过数学表达式计算出元素的内存地址,所以检索效率最高。】;向数组末尾添加元素,效率很高,不受影响
    数组缺点:随机增删元素效率比较低;数组无法存储大数据量【很难找到一块非常巨大的连续的内存空间】
  3. 面试问题:这么多的集合中,哪个集合用的最多?
    答:ArrayList集合,因为往数组末尾添加元素,效率不受影响,另外,检索/查找某个元素的操作比较多
  4. ArrayList集合是非线程安全的(不是线程安全的集合)

3.2.1 位运算符

package Collectice;

public class BinaryTest {
    public static void main(String[] args) {

        // >> 1 二进制右移1位
        // >> 2 二进制右移2位
        //10的二进制位是:00001010 【10】
        //10的二进制右移1位是:00000101 【5】
        System.out.println(10 >> 1);//输出为:5


        //二进制左移1位
        //10的二进制位是:00001010 【10】
        //10的二进制左移1位是:00010100 【20】
        System.out.println(10 << 1);//输出为:20
    }
}

3.2.2 ArrayList构造方法

package Collectice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

public class ArrayListTest02 {
    public static void main(String[] args) {

        //默认初始化容量10
        List myList1 = new ArrayList();

        //指定初始化容量100
        List myList2 = new ArrayList(100);

        //创建了HashSet集合
        Collection c = new HashSet();

        //添加元素到set集合
        c.add(100);
        c.add(200);
        c.add(900);
        c.add(500);

        //通过这个构造方法就可以将HashSet集合转换成List集合
        List myList3 = new ArrayList(c);
        for (int i = 0; i < myList3.size(); i++) {
            System.out.println(myList3.get(i));
        }
    }
}

运行结果

在这里插入图片描述

3.3 LinkedList

  1. LinkedList集合是双向链表(看源码)
  2. 对于链表数据结构来说,随机增删效率较高,检索效率较低
  3. 链表中的元素在空间存储上,内存地址不连续

3.3.1 单向链表结构

链表优缺点备注
优点由于链表上的元素在空间存储上内存地址不连续。所以随机增删元素的时候不会有大量元素位移,因此随机增删效率较高。在以后的开发中,如果遇到随机增删集合中元素的业务比较多时,建议使用LinkedList。
缺点不能通过数学表达式计算被查找元素的内存地址,每一次查找都是从头节点开始遍历,直到找到为止。所以LinkedList集合检索/查找的效率较低。

ArrayList:把检索发挥到极致(末尾添加元素效率还是很高的)
LinkedList:把随机增删发挥搭配极致
加元素都是往末尾添加,所以ArrayList用的比LinkedList多

单链表中的节点
节点是单向链表中基本的单元,每一个节点Node都有两个属性:

  • 属性1:是存储的数据
  • 属性2:是下一个节点的内存地址
package danlink;

public class Node {

    //存储的数据
    Object element;

    //下一个节点的内存地址
    Node next;

    public Node() {
    }

    public Node(Object element, Node next) {
        this.element = element;
        this.next = next;
    }
}

链表

package danlink;

public class Link {


    //头节点
    Node header;

    int size = 0;

    public int size(){
        return size;
    }

    //向链表中添加元素的方法(向某尾部添加)
    public void add(Object data) {

        //创建一个新的节点对象
        //让之前的单链表的某尾节点next指向新节点对象
        //有可能这个元素是第一个,也可能是第二个
        if (header == null){
            //说明还没有节点
            //new一个新的节点对象,作为头节点对象
            //这个时候的头节点既是一个头节点,又是一个末尾节点
            header = new Node(data,null);
        }else {
            //说明头不是空,头节点已有
            //找出当前某尾节点,让当前末尾节点的next是新节点
            Node currentLastNode = findLast(header);
            currentLastNode.next = new Node(data,null);

        }

        size++;
    }

    /**
     * 专门查找末尾节点的方法
     * @param
     * @return
     */
    private Node findLast(Node node) {
        if (node.next == null){
            //如果一个节点的next是null
            //说明这个节点就是末尾节点
            return node;
        }

        //程序能够到这里说明:node不是末尾节点
        return findLast(node.next);//递归算法!
    }

    //删除链表中某个数据的方法
    public void remove(Object obj) {

    }

    //修改链表中某个数据的方法
    public void modify(Object newObj) {

    }

    public int find(Object obj) {
        return 1;
    }
}

测试类

package danlink;

public class Test {
    public static void main(String[] args) {

        //创建了一个集合对象
        Link link = new Link();

        //往集合中添加元素
        link.add(100);
        link.add(200);
        link.add(300);
        link.add(400);

        //获取元素个数
        System.out.println(link.size());//输出为:4
    }
}

注意

  1. LinkedList集合底层也是有下标的
  2. ArrayList之所以检索效率比较高,不是单纯因为下标的原因,是因为底层数组发挥的作用
  3. LinkedList集合照样有下标,但是检索/查找某个元素的时候效率比较低,因为只能从头节点开始一个一个遍历

3.3.2 双向链表结构

内存演示图

在这里插入图片描述

package danlink;

public class Test {
    public static void main(String[] args) {

        //创建了一个集合对象
        List list = new LinkedList();

        //往集合中添加元素
        list.add("a");
        list.add("b");
        list.add("c");

        //获取元素个数
        for(int i = 0;i < list.size();i++){
            Object obj = list.get(i);
            System.out.println(obj);
        }
    }
}

内存演示图

在这里插入图片描述
方法执行后内存释放:

在这里插入图片描述
注意:LinkedList集合没有容量初始化;最初这个链表中没有任何元素,first和last引用都是null;

3.4 Vector

  1. 底层也是一个数组
  2. 初始化容量:10
  3. 扩容之后是原容量的2倍:10–>20–>40–>80
    ArrayList集合扩容特点:10–>15–>15*1.5
  4. Vector中所有的方法都是线程同步的,都带有synchronized关键字,是线程安全的,效率比较低,使用较少了。
  5. 将一个线程不安全的ArrayList集合转换成线程安全的:
    使用集合工具类:java.util.Collections;
    注意:
    java.util.Collection 是集合接口
    java.util.Collections 是集合工具类
import java.util.*;

public class VectorTest {
    public static void main(String[] args) {
        //创建一个Vector集合
        Vector vector = new Vector();

        //添加元素
        //默认容量10个
        vector.add(1);
        vector.add(2);
        vector.add(3);
        vector.add(4);
        vector.add(5);
        vector.add(6);
        vector.add(7);
        vector.add(8);
        vector.add(9);
        vector.add(10);

        //满了之后扩容
        vector.add(11);

        Iterator it = vector.iterator();

        while (it.hasNext()){
            System.out.println(it.next());
        }

        //以后使用
        List myList = new ArrayList();//非线程安全的

        //变成线程安全的
        Collections.synchronizedList(myList);//学会多线程后可看效果

        //myList集合就是线程安全的
        myList.add("111");
        myList.add("222");
        myList.add("333");
    }
}

4.泛型机制

  1. JDK5.0之后推出的新特性:泛型
  2. 泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的(运行阶段泛型没用!)
  3. 泛型好处:
    第一:集合中存储的元素类型统一了
    第二:从集合中取出的元素类型是泛型指定的类型,不需要进行大量的“向下转型”!
  4. 泛型缺点:导致集合中存储的元素缺乏多样性!
  5. 大多数业务中,集合中元素的类型还是统一的,所以这种泛型特性被大家所认可

4.1 不使用泛型

package Collectice;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class GenericTest01 {
    public static void main(String[] args) {
        //不使用泛型机制,分析程序存在缺点
        //创建集合
        List myList = new ArrayList();

        //准备对象
        Cat c = new Cat();
        Bird b = new Bird();

        //将对象添加到集合当中
        myList.add(c);
        myList.add(b);

        //遍历集合,取出每个Animal,让它move
        Iterator it = myList.iterator();
        while (it.hasNext()){
            //没有这个语法,通过迭代器取出的就是Object
            //Animal a = it.next();

            Object obj = it.next();
            //obj中没有move方法,无法调用,需要向下转型!、
            if (obj instanceof Animal){
                Animal a = (Animal) obj;
                a.move();
            }
        }
    }
}

class Animal{
    //父类自带方法
    public void move(){
        System.out.println("动物在移动!");
    }
}

class Cat extends Animal{
    //特有方法
    public void catchMouse(){
        System.out.println("猫抓老鼠!");
    }
}

class Bird extends Animal{
    //特有方法
    public void fly(){
        System.out.println("鸟儿在飞翔!");
    }
}

运行结果

在这里插入图片描述

4.2 使用泛型

package Collectice;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class GenericTest02 {
    public static void main(String[] args) {
        //使用JDK5之后的泛型机制
        //使用泛型List<Animal>之后,表示List集合只运行存储Animal类型的数据
        //用泛型来指定集合中存储的数据类型
        List<Animal> myList = new ArrayList<Animal>();

        //指定List集合中只能存储Animal,那么存储String就编译报错了
        //这样用了泛型之后,集合中元素的数据类型更加统一了
        //myList.add("abc");

        //准备对象
        Cat c = new Cat();
        Bird b = new Bird();

        myList.add(c);
        myList.add(b);

        //获取迭代器
        //这个表示迭代器迭代的是Animal类型
        Iterator<Animal> it = myList.iterator();
        while (it.hasNext()){
            //使用泛型之后,每一次迭代返回的数据都是Animal类型
            Animal a = it.next();
            //这里不需要进行强制类型转换了,直接调用
            a.move();

            //调用子类型特有的方法还说需要向下转型的
            Animal e = it.next();
            if (e instanceof  Cat){
                Cat x = (Cat) e;
                x.catchMouse();
            }
            if (e instanceof  Bird){
                Bird y = (Bird) e;
                y.fly();
            }
        }
    }
}
class Animal{
    //父类自带方法
    public void move(){
        System.out.println("动物在移动!");
    }
}

class Cat extends Animal{
    //特有方法
    public void catchMouse(){
        System.out.println("猫抓老鼠!");
    }
}

class Bird extends Animal{
    //特有方法
    public void fly(){
        System.out.println("鸟儿在飞翔!");
    }
}

4.3 自动类型推断机制(钻石表达式)

package Collectice;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class GenericTest03 {
    public static void main(String[] args) {
        //ArrayList<这里的类型会自动推断>() 前提是JDK8之后才允许的
        //自动类型推断,钻石表达式!
        List<Animal> myList = new ArrayList<>();

        myList.add(new Animal());
        myList.add(new Cat());
        myList.add(new Bird());

        //遍历
        Iterator<Animal> it = myList.iterator();
        while (it.hasNext()){
            Animal a = it.next();
            a.move();
        }
    }
}

class Animal{
    //父类自带方法
    public void move(){
        System.out.println("动物在移动!");
    }
}

class Cat extends Animal{
    //特有方法
    public void catchMouse(){
        System.out.println("猫抓老鼠!");
    }
}

class Bird extends Animal{
    //特有方法
    public void fly(){
        System.out.println("鸟儿在飞翔!");
    }
}

4.4 自定义泛型

  1. 自定义泛型的时候,<>尖括号中的是一个标识符,随便写
  2. 用泛型就被固定了,不用泛型就是Object类型
  3. java源代码中经常出现的是:< E >和< T >
    E是Element单词首字母;T是Type单词首字母
package Collectice;

public class GenericTest04 <标识符随便写>{

    public void doSome(标识符随便写 o){
        System.out.println(o);
    }

    public static void main(String[] args) {
        //new对象的时候指定了泛型是:String类型
        GenericTest04<String> gt = new GenericTest04<>();

        //类型不匹配
        //gt.doSome(100);

        gt.doSome("abc");
    }
}

5.foreach

  1. JDK5.0之后推出了一个新特性:叫做增强for循环,或者叫做foreach
  2. 语法格式:
for(元素类型 变量名 : 数组或集合){
  System.out.println(变量名);
}
  1. foreach缺点:没有下标
  2. 在需要使用下标的循环中,不建议使用增强for循环

5.1 foreach正常案例

package Collectice;

public class ForEachTest01 {
    public static void main(String[] args) {
        //int类型数组
        int[] arr = {432,4,65,45,76,11,2};

        //遍历数组(普通for循环)
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        System.out.println("========================");

        //foreach方法
        for (int data : arr) {
            //data就是数组中的元素(数组中的每一个元素)
            System.out.println(data);
        }
    }
}

运行结果

在这里插入图片描述

5.2 foreach在集合中的使用

package Collectice;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ForEachTest02 {
    public static void main(String[] args) {
        //创建List集合
        List<String> strList = new ArrayList<>();

        //添加元素
        strList.add("hello!");
        strList.add("world!");
        strList.add("kitty!");

        //遍历,使用迭代器方式
        Iterator<String> it = strList.iterator();
        while (it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }

        //使用下标方式(只针对于有下标的集合)
        for (int i = 0; i < strList.size(); i++) {
            System.out.println(strList.get(i));
        }

        //使用foreach
        for(String s : strList){//因为泛型使用的是String类型,所以是:String s
            System.out.println(s);
        }
    }
}
举报

相关推荐

0 条评论