文章目录

  • JAVA集合
  • 对象数组
  • JAVA集合概述:
  • Collection集合的功能概述:
  • JAVA集合——list类
  • List概述及特点
  • List的遍历:(案例)
  • ListIterator的特有功能:
  • List的三个子类的特点:
  • 并发修改异常产生的原因及解决方案
  • 数据结构的理解与特性
  • JAVA集合——ArrayList
  • ArrayList存储与遍历
  • 案例:(去除ArrayList中的重复数值)
  • Java集合——Vector
  • Vector的概述:
  • Vector类特有功能:
  • JAVA集合——LinkedList
  • LinkedList概述:
  • LinkedList特有的功能:
  • LinkedList案例:(模拟栈的数据结构)
  • JAVA泛型:
  • 概述和基本使用:
  • 泛型的好处的演示:(自定义类中使用泛型!)
  • 多泛型的使用:
  • 泛型接口的概述和使用
  • 泛型在方法上的使用:
  • 泛型高级之通配符:
  • 增强for循环:
  • JAVA可变参数:
  • Arrays工具类的asList()方法的使用:
  • JAVA 嵌套集合:(ArrayList嵌套ArrayList)

JAVA集合

对象数组
  • 案例:
    需求:我有3个学生,请把这个3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。
  • 代码示例:(Student类定义)
public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
  • 代码示例:(主函数示例:)
public class MyTest {
    public static void main(String[] args) {
        //需求:我有3个学生,请把这个3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。
        //		  学生:Student
        //			成员变量:name,age
        //			构造方法:无参,带参
        //			成员方法:getXxx()/setXxx()
        //			存储学生的数组?自己想想应该是什么样子的?

        Student s1 = new Student("苏沅湘", 20);
        Student s2 = new Student("崔季宣", 20);
        Student s3 = new Student("周颖", 18);
        //把要把上面三个学生对象存储起来
        //创建对象数组
        Student[] students={s1,s2,s3};
        //遍历对象数组
        for (int i = 0; i < students.length; i++) {
            Student student = students[i];
            System.out.println(student.getName()+"==="+student.getAge());
        }
        //删掉数组中的第三个元素
        Student[] students1 = Arrays.copyOf(students, 2);
        System.out.println(Arrays.toString(students1));
    }
}
----------------------
输出:
苏沅湘===20
崔季宣===20
周颖===18
[org.westos.demo.Student@1b6d3586, org.westos.demo.Student@4554617c]
  • 根据以上案例可以得到的结论:
    a. 数组作为容器:可以存储多种多样的类型,但是数组作为容器,增删数组中的元素是很不方便的。
    b. 正因为如此,那Java为了我们更方便的去操作(增删改查)容器中的元素,给我们提供了另外一个容器,叫做集合
JAVA集合概述:
  • 概念:
    Java为了我们更方便的去操作(增删改查)容器中的元素(数组的操作有弊端!),给我们提供了另外一个容器,叫做集合。
    面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类。
  • 数组和集合的区别:
    数组:可以存储基本数据类型,也可以存储引用数据类型。
    集合:只能存储引用数据类型
    数组:一定定义,长度不可变
    集合:长度是可变的。
    数组:只能存储同一种数据类型
    集合:可以存储多种数据类型
  • JAVA中由很多类型的集合,具体可以参考**“Collection集合的继承体系:”**
  • Java列表和列表嵌套 java中list嵌套list_JAVA

Collection集合的功能概述:
  • Collection 接口 是个单列集合的父类:
    示例:
public class MyTest {
    public static void main(String[] args) {
        // Collection 接口 是个单列集合的父类
        //多态(重点),从继承图中可知:ArrayList是Collection的子类!
        Collection collection = new ArrayList();
        //往集合中添加元素,返回值的意思是 是否添加成功
        boolean b = collection.add("aaa");
        collection.add("bbb");
        collection.add("ccc");

        System.out.println(collection);
    }
}
--------------
输出:
[aaa, bbb, ccc]
  • 具体的集合功能可以通过查看API说明手册看到,以下只一部分常用的举例:
  • 功能示例:
    a. 添加功能
boolean add(Object obj):		添加一个元素(返回的是是否成功)
boolean addAll(Collection c):	添加一个集合的元素  (给一个集合添加进另一个集合中的所有元素)
---------------------
示例:
Collection collection1 = new ArrayList();
collection1.add(100); //自动装箱
collection1.add(Integer.valueOf(20));
collection1.add(300);
collection1.add(400);
//删掉集合中的元素
boolean b = collection1.remove(400);
System.out.println(collection1);
//清空集合中集合中的元素
collection1.clear();
System.out.println(collection1);
输出:
[aaa, bbb, ccc, 100, 20, 300, 400]
[100, 20, 300, 400]
  • b. 删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c):移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素,如果没有交集元素 则删除失败 返回false
------------------------
示例1:
Collection collection1 = new ArrayList();
collection1.add(100); //自动装箱(因为集合中存储的是引用类型!,所以自动装箱成Integer类型的数据!)
collection1.add(Integer.valueOf(20));//手动装箱
collection1.add(300);
collection1.add(400);
//删掉集合中的元素
boolean b = collection1.remove(400);
System.out.println(collection1);
//清空集合中集合中的元素
collection1.clear();
System.out.println(collection1);
输出:
[100, 20, 300]
[]
-------------------
示例2:
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(2000);
collection1.add(500);
Collection collection2 = new ArrayList();
collection2.add(100); //自动装箱
collection2.add(400);
//A集合removeAll(B集合) A 集合会移除掉两个集合的交集元素,如果移除了返回true,没有交集元素返回false
boolean b = collection1.removeAll(collection2);
System.out.println(b);
System.out.println(collection1);
System.out.println(collection2);
输出:
false
[1000, 2000, 500]
[100, 400]
  • c. 判断功能
boolean contains(Object o):判断集合中是否包含指定的元素	
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(这个集合包含另一个集合中所有的元素才算包含 才返回true),比如:1,2,3 containsAll 12=true   1,2,3 containsAll 2,3,4=false。
boolean isEmpty():判断集合是否为空
--------------------------
示例1:
//与判断相关的方法
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(4000);
collection1.add(500);
//判断集合中是否有这个元素
boolean b = collection1.contains(500);
System.out.println(b);
输出:
true
------------------------
示例2:
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(500);
//获取集合的长度
int size = collection1.size();
System.out.println(size);
collection1.clear();
//判断一个集合是否为空
boolean empty = collection1.isEmpty();
System.out.println(empty);
//"".isEmpty(); 字符串也有一个判断是否为空的方法!
  • d. 获取功能:集合只能通过迭代器进行迭代!
Iterator<E> iterator()(重点)
-----------------------
示例:
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(2000);
collection1.add(3000);
collection1.add(4000);
collection1.add(4000);
collection1.add(500);

//遍历Collection集合需要获取一个迭代器
//对 collection 进行迭代的迭代器
/* boolean hasNext ()
如果仍有元素可以迭代,则返回 true。
E next ()
返回迭代的下一个元素。*/

// 接口 Iterator<E >
Iterator iterator = collection1.iterator();
//java.util.ArrayList$Itr @ 1 b6d3586
Object next = iterator.next();//手动移动
System.out.println(next);
System.out.println(iterator);
while (iterator.hasNext()){
    Object obj= iterator.next();
    System.out.println(obj);
}
System.out.println(collection1);
输出:
1000
java.util.ArrayList$Itr@1b6d3586(这个iterator是一个内部类的对象!(通过打印地址值发现!,但通过追踪源码我无法得出此结论!))
								  定义为内部类的好处:可以直接访问集合中的对象!(内部类可以访问外部类的信息!)
2000
3000
4000
4000
500
[1000, 2000, 3000, 4000, 4000, 500] (说明迭代器进行迭代的时候,只是迭代指针发生了变化,而集合本身并没有发生滨化!)
----------------------------------
示例2:(Student类的定义在本文第一部分已经给出了)
Student s1 = new Student("苏沅湘", 20);
Student s2 = new Student("崔季宣", 20);
Student s3 = new Student("周颖", 18);
Collection collection = new ArrayList();
collection.add(s1);
collection.add(s2);
collection.add(s3);
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
    Object next = iterator.next();
    //向下转型
    Student student= (Student) next;
    System.out.println(student.getName()+"==="+student.getAge());
    }
-------------------------
输出:
苏沅湘===20
崔季宣===20
周颖===18
  • e. 长度功能
int size():元素的个数
面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?
回答:数组有,字符串有,集合没有(集合是size)。
  • f. 交集功能
例如:A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化 
boolean retainAll(Collection c):获取两个集合的交集元素(交集:两个集合都有的元素)
----------
示例:
//取两个集合的交集元素
    Collection collection1 = new ArrayList();
    collection1.add(100); //自动装箱
    collection1.add(200);
    collection1.add(300);
    collection1.add(400);
    collection1.add(4000);
    collection1.add(500);

    Collection collection2 = new ArrayList();
    collection2.add(100); //自动装箱
    collection2.add(200);
    collection2.add(300);
    collection2.add(400);
    collection2.add(600);
	//例如:A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化 发生过变化返回true 没有发生变化返回false
    boolean b = collection1.retainAll(collection2);
    System.out.println(b);
    System.out.println(collection1);
    System.out.println(collection2);
    输出:
    true
	[100, 200, 300, 400](collection1中只剩下了交集的元素)
	[100, 200, 300, 400, 600](collection2的元素未发生变化)
  • g. 把集合转换为数组
Object[] toArray()
---------------
示例:
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(2000);
collection1.add(3000);
collection1.add(4000);
collection1.add(4000);
collection1.add(500);
把一个集合转换成数组(手动版:)
Integer[] integers = new Integer[collection1.size()];
Iterator iterator = collection1.iterator();
int i=0;
while (iterator.hasNext()){
    Object next = iterator.next();
    Integer integer= (Integer) next;
    integers[i++]=integer;
}
System.out.println(Arrays.toString(integers));
toArray();把一个集合转换成数组(这个数组是Object型的)
Object[] objects = collection1.toArray();
//遍历途中可以对元素进行向下转型(必须向下转型才能获取相应的数值!)
for (int j = 0; j < objects.length; j++) {
    Integer object = (Integer) objects[j];
    System.out.println(object.intValue());
}
输出:
[1000, 2000, 3000, 4000, 4000, 500]
1000
2000
3000
4000
4000
500
  • IDEA小技巧:按住alt操作鼠标,多列选中,对多列同时进行操作!
JAVA集合——list类
List概述及特点
  • List概述及特点: 元素有序,并且每一个元素都存在一个索引.元素可以重复.(这里的有序指的是:可以通过索引来获取元素!)
  • List集合的特有功能概述:
void add(int index,E element):		在指定索引处添加元素
E remove(int index):				移除指定索引处的元素  返回的是移除的元素
E get(int index):					获取指定索引处的元素
E set(int index,E element):			更改指定索引处的元素 返回的而是被替换的元素
  • 根据元素查找索引:
int index = list.indexOf(100);
int index2 = list.lastIndexOf(100);
  • 遍历集合中的元素:(相当于创建了一个匿名内部类)
list.forEach(new Consumer()){
    @Override
    public void accept(Object o){
        System.out.println(o);
    }
}
  • 上面遍历的方法可以用Lambda进行简化表示:(简化上面匿名内部类的写法!)
//可以使用Lambda 简化上面的写法
System.out.println("===========================");
list.forEach((obj)->System.out.println(obj));
List的遍历:(案例)
  • 案例:List集合遍历(应该有三种方法:两种迭代器,一种for循环)
public class MyTest3 {
    public static void main(String[] args) {
        List list = new ArrayList();

        list.add(1000); //自动装箱
        list.add(2000);
        list.add(3000);
        list.add(4000);
        list.add(4000);
        list.add(500);
        
        //遍历方式1: 利用Colletction的迭代器
        //list.iterator()
        //遍历方式2:List 有一个自己的迭代器
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
            Object next = listIterator.next();
            System.out.println(next);
        }
        System.out.println("==============================");
        //遍历方式3 采用for循环遍历
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
    }
}
---------
输出:

1000
2000
3000
4000
4000
500
==============================
1000
2000
3000
4000
4000
500
  • 案例:List集合存储学生对象并遍历
public class MyTest4 {
    public static void main(String[] args) {
        Student s1 = new Student("苏沅湘", 20);
        Student s2 = new Student("崔季宣", 20);
        Student s3 = new Student("周颖", 18);
        List arrayList = new ArrayList();
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        for (int i = 0; i < arrayList.size(); i++) {
            Object o = arrayList.get(i);
            Student student= (Student) o;
            System.out.println(student.getName()+"==="+ student.getAge());
        }
    }
}
-------------
输出:
苏沅湘===20
崔季宣===20
周颖===18
ListIterator的特有功能:
  • 概念:ListIterator 继承自Iterator 可以使用Iterator中的方法
  • ListIterator的特有功能:
boolean hasPrevious():			是否存在前一个元素
	E previous():					返回列表中的前一个元素
  • 注意:
    a. 以上两个方法组合可以实现反向遍历,但是注意:要完成反向遍历之前要先进行正向遍历 ,这样指针才能移到最后
    b. 如果直接反向遍历是没有效果的 ,因为指针默认位置就在最前面 他前面没有元素。
List的三个子类的特点:
  • List的三个子类的特点:
  • ArrayList:
    底层数据结构是数组,查询快,增删慢。
    线程不安全,效率高。
  • Vector:
    底层数据结构是数组,查询快,增删慢。
    线程安全,效率低。
  • LinkedList:
    底层数据结构是链表,查询慢,增删快。
    线程不安全,效率高。
  • List有三个子集合,我们到底使用谁呢?
    要安全还是要效率?
    是查找多还是增删多?
    (根据以上特性来选择!)
并发修改异常产生的原因及解决方案
  • 案例演示:(需求:我有一个集合,我想判断里面有没有 “world” 这个元素,如果有,我就添加一个 “javaee” 元素,请写代码实现。)
public class MyTest2 {
    public static void main(String[] args) {
      /*  需求:我有一个集合,请问,我想判断里面有没有 "world" 这个元素,
      如果有,我就添加一个 "javaee" 元素,请写代码实现。*/
        List list = new ArrayList();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("world");

		方式1:
       /* if (list.contains("world")) {
            list.add("javaee");
        }
        System.out.println(list);
*/
		方式2:
        // ConcurrentModificationException 并发修改异常
        //当你使用迭代器,对集合的元素,进行迭代,那么在迭代途中,先要增删集合中的元素,就会出现并发修改异常
        //为什么?是因为,通过集合获取到,这个迭代器之后,迭代器,已经预先知道,集合中的元素个数,会按照既定的元素个数进行迭代,那么在迭代途中,你突然要增删元素,就会打乱迭代器的迭代顺序,所以就会抛出并发修改异常
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()) {
            Object next = listIterator.next();
            String ele = (String) next;
            if (ele.equals("world")) {
                //list.add("javaee");  	// 这样的写法会报错
                //  list.remove("aaa");	// 这样的写法会报错
                listIterator.add("javaee");
            }
        }
       	System.out.println(list);
       	//方式3 使用for循环遍历

        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).equals("aaa")) {
                list.add("vvvv");
            }
        }
        System.out.println(list);
    }
}
  • ConcurrentModificationException 并发修改异常:
    当你使用迭代器,对集合元素,进行迭代,那么在迭代途中,如果要增删集合中的元素,就会出现冰法修改异常
  • 原因:
    因为,通过集合获取到这个迭代器之后,迭代器,已经预先知道,集合总的元素个数,会按照既定的元素个数进行迭代,那么在迭代途中,你突然要增删元素,就会打乱迭代其的迭代顺序,所以就会抛出并发修改异常。
  • 解决方式:
    解决方式1:(如果使用迭代器遍历,那么在遍历途中,想要增删元素,那么你就使用迭代器自带的增删元素的方法)
    解决方式2:使用for循环遍历
数据结构的理解与特性
  • 数据结构概述及常见数据结构:
    数据结构其实就是存储数据的格式
    分类: 栈 , 队列 , 数组 , 链表 , 树 , 哈希表
  • 栈特点: 先进后出
  • 队列: 先进先出
  • 数组特点: 查询快 , 增删慢
  • 链表特点: 查询慢 , 增删快
JAVA集合——ArrayList
ArrayList存储与遍历
  • JDK1.8新增的一个方法也能遍历集合
    void forEach(Consumer<? super E> action) 执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常
  • 其他遍历操作:
迭代器(因为ArrayList还是List的子类,可以利用Collection的迭代器或者List独有的迭代器)
普通for(因为ArrayList还是List的子类)
  • 示例:
public class MyTest {
    public static void main(String[] args) {
        //
        ArrayList list = new ArrayList(); ArrayList指向(这次与以往不同,不是由Collection或者List指向它,利用多态进行访问了!)
      	/*  int lastIndexOf (Object o)
        返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 - 1。
        int indexOf (Object o)
        返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 - 1。
        void forEach (Consumer < ? super E > action)
        执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常。*/

        list.add(100);
        list.add(200);
        list.add(300);
        list.add(100);
        list.add(400);
        list.add(500);
        //根据元素查找改元素第一次出现的索引
        int index = list.indexOf(100);
        System.out.println(index);
        int i = list.lastIndexOf(100);
        System.out.println(i);

        for (int i1 = 0; i1 < list.size(); i1++) {
            System.out.println(list.get(i1));
        }
        System.out.println("===========================");
        //Consumer
        //遍历集合中的元素
        list.forEach(new Consumer() {
            @Override
            public void accept(Object o) {
                System.out.println(o);
            }
        });
        //可以使用Lambda 简化上面的写法
        System.out.println("===========================");
        list.forEach((obj)->System.out.println(obj));
    }
}
案例:(去除ArrayList中的重复数值)
  • 示例1:(不采取额外的存储结构)
public class MyTest2 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(100);
        list.add(100);
        list.add(100);
        list.add(100);
        list.add(100);
        list.add(100);
        list.add(200);
        list.add(100);
        list.add(200);
        list.add(100);
        list.add(200);
        list.add(100);
        list.add(200);
        list.add(300);
        list.add(100);
        list.add(400);
        list.add(500);
        list.add(100);
        list.add(200);
        list.add(300);
        list.add(100);
        list.add(400);
        list.add(500);
        list.add(100);
        list.add(200);
        list.add(100);
        list.add(200);
        //去除集合中的重复元素
        //每次拿一个元素,跟后面的每个元素取比较,如果遇到相同的,就删除
        for (int i = 0; i < list.size(); i++) {
            for (int j = i + 1; j < list.size(); j++) {
               /* Object o = list.get(i);
                Object o1 = list.get(j)*/;
                if(list.get(i).equals(list.get(j))){
                    list.remove(j);
                    j--;//记得 j--(重点!)
                }
            }
        }
        System.out.println(list);

      //  HashSet hashSet = new HashSet<>(list);
      //  System.out.println(hashSet);
    }
}
  • 示例2:去除集合中字符串的重复值(可以采用辅助的数据结构)
public class MyTest {
    public static void main(String[] args) {
        /*A:
        案例演示
        需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
        思路:创建新集合方式*/
        ArrayList list = new ArrayList();
        list.add("abc");
        list.add("abc");
        list.add("abc");
        list.add("abc");
        list.add("bbb");
        list.add("abc");
        list.add("ccc");
        list.add("aaa");

        ArrayList newList = new ArrayList();
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            if(!newList.contains(o)){
                newList.add(o);
            }
        }
        System.out.println(newList);
    }
}
-------------
输出:
[abc, bbb, ccc, aaa]
  • 示例3:(去除自定义类对象的重复值,即:对象的成员变量值相同)
    自定义学生类:
public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public boolean equals(Object o) {   //必要的重写部分:
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, );
    }


    @Override
    public int hashCode() {   //非必要重写这部分!
        return Objects.hash(name, age);
    }
}
  • 主函数:
public class MyTest2 {
    public static void main(String[] args) {
        Student s1 = new Student("张三", 23);
        Student s2 = new Student("张三", 23);
        Student s3 = new Student("张三", 23);
        Student s4 = new Student("张三2", 23);
        Student s5 = new Student("张三3", 23);
        ArrayList list = new ArrayList();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        list.add(s5);
        ArrayList newList = new ArrayList();
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            if(!newList.contains(o)){   重点在这里,为何它可以对比出不同对象是否是我们要删除的标准?
                newList.add(o);
            }
        }

        System.out.println("=============");
        for (int i = 0; i < newList.size(); i++) {
           Student stu = (Student) newList.get(i);
            System.out.println(stu.getName()+"==="+stu.getAge());
        }
        
    }
}
-------------------
输出:
=============(这里刚好得到我们想要的结果!)
张三===23
张三2===23
张三3===23
  • 引出问题:contains()为何能知道我们比对的标准是什么?
    追踪contains()源码可知:
在ArrayList.java文件下,得到:
public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
-------------------
进一步追踪,这里的indexOf()就是ArrayList.java下的indexOF()
public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))   发现了重点:它会调用对象的equals()方法进行对比!(恰好我们在自定义的Student类中重写了equals()方法!,所以达到了我们想要的对比效果!)
                    return i;
        }
        return -1;
    }
Java集合——Vector
Vector的概述:
  • 概述:Vector 类可以实现可增长的对象数组 , Vector 是同步的。
  • 特点:Vector 底层数据结构是数组,查询快,增删慢,线程安全效率低
Vector类特有功能:
  • 功能:
public void addElement(E obj) 添加元素的另一种方法
public E elementAt(int index) 获取元素的另一种方法
public Enumeration elements() 返回可迭代的迭代器
  • 案例演示:
public class MyTest {
    public static void main(String[] args) {
       //Vector 底层数据结构是数组,查询快,增删慢,线程安全效率低

      /*  public void addElement (E obj)
        public E elementAt ( int index)
        public Enumeration elements ()*/
        Vector vector = new Vector();
        vector.add(200);
        vector.addElement(
        300);
        vector.add(200);
        vector.addElement(300);
        vector.add(200);
        vector.addElement(300);
        Object ox = vector.get(0);
        Object o1 = vector.elementAt(0);
        System.out.println(o1 == ox); 返回true,则说明这两种取元素的方法效果是一致的!
         /* 
        lastElement()返回向量的最后一个组件。
        firstElement()返回第一个组件(在指数 0项目)这个载体。
        removeElement(Object obj)从该向量中移除第一个(最低索引)发生的参数。
        void removeElementAt(int index)在指定的索引中删除组件。
        setElementAt(E obj, int index)设置组件在指定的index这个向量是指定的对象。

        */
         //遍历方法:
        Enumeration elements = vector.elements();
        while (elements.hasMoreElements()){
            Object o = elements.nextElement();
            System.out.println(o);
        }
        
    }
}
----------------
输出:
true
200
300
200
300
200
300
JAVA集合——LinkedList
LinkedList概述:
  • 概述:List 接口的链接列表实现 , 此实现不是同步的
  • 特点:LinkedList 底层数据结构是链表,增删快查询慢,线程不安全效率高
LinkedList特有的功能:
  • 功能:
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
  • 特有功能示例:
public class MyTest {
    public static void main(String[] args) {
        //LinkedList 底层数据结构是链表,增删快查询慢,线程不安全效率高
        /*
          void addFirst(E e)在此列表的开始处插入指定的元素。
          void addLast(E e)将指定的元素列表的结束。
          public void addFirst(E e)及addLast(E e)
	      public E getFirst()及getLast()
	      public E removeFirst()及public E removeLast()
        */
        LinkedList linkedList = new LinkedList();
        linkedList.addLast("eeee");
        linkedList.add("aaa");
        linkedList.addFirst("bbb");
        linkedList.add("ccc");
        System.out.println(linkedList);

        Object o = linkedList.get(0);
        System.out.println(o);
        Object first = linkedList.getFirst();
        System.out.println(first);
        Object first2 = linkedList.getFirst();
        System.out.println(first2);
        
        System.out.println(linkedList);
    }
}
-------------
输出:
[bbb, eeee, aaa, ccc]
bbb
bbb
bbb
[bbb, eeee, aaa, ccc]
LinkedList案例:(模拟栈的数据结构)
  • 示例:(自定义List类)
public class MyList {
    LinkedList linkedList;
    public MyList() {
        linkedList= new LinkedList();
    }

    public void addObj(Object obj) {
       linkedList.addFirst(obj);
    }

    public Object get() {
        Object obj= linkedList.pop();
        linkedList.addLast(obj);  //这样做的目的是:操作完后,原来的数据还在!(但个人感觉好像挺没必要的!)
        return obj;
    }
}
  • 示例2:(主函数)
public class MyTest {
    public static void main(String[] args) {
        //需求:请用LinkedList模拟栈数据结构的集合,并测试

        MyList myList = new MyList();
        myList.addObj(100);
        myList.addObj(200);
        myList.addObj(300);
        myList.addObj(400);
        myList.addObj(500);

        Object obj=myList.get();
        System.out.println(obj);
        obj = myList.get();
        System.out.println(obj);
        obj = myList.get();
        System.out.println(obj);
        obj = myList.get();
        System.out.println(obj);
        obj = myList.get();
        System.out.println(obj);
        System.out.println("==============");
        obj = myList.get();
        System.out.println(obj);
    }
}
-----------------
输出:
500
400
300
200
100
==============
500(这里可以看到,当遍历完一回以后,数据元素没有发生变化!)
JAVA泛型:
概述和基本使用:
  • 泛型的由来:
    ObjectTool
    泛型的由来:通过Object转型问题引入
    早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。
    也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
  • 概念:
    如果我们使用了泛型,就可以明确集合中到底放了什么样的数据类型。
    泛型机制:是JDK1.5引入的,是一种将数据类型明确的工作,推迟到创建对象,或调用方法时,再去明确的一种机制。
    也就是:参数化类型,把类型当作参数一样的传递。
  • 定义方法:
泛型可以使用在类、接口 方法 <引用类型,引用类型>
------------------
例如:(在创建ArrayList对象的时候传入指定的泛型为:String,则ArrayList中只能存储这一种类型,若不传入:则默认为:Object类型,所以获取的时候,需要显示地进行向下转换!)
ArrayList<String> list1 = new ArrayList<Sring>()
  • 泛型的好处:
    (1): 把运行时期的问题提前到了编译期间(这句话的含义不太懂?难道是指的避免了运行时候向下转换所造成的报错?这个编译器和运行期到底怎么解释的?编译器不行但是运行期可以(反射)?)
    (2): 避免了强制类型转换
    (3):优化了程序设计,解决了黄色警告线
  • 集合明确了泛型的具体类型,那么这个集合就只能存储这种类型(避免向下转型)
    示例:
示例:(避免向下转型)
查看上课所述!
//集合可以存储多种引用数据类型。
ArrayList list = new ArrayList();(这里没有专门指定泛型的类型声明,则默认为:Object)
list.add("abc");
list.add(200);
list.add(new StringBuffer());
Object o = list.get(0);
String str= (String) o;(向下转型)
int length = str.length();
-------------------------
//集合明确了泛型的具体类型,那么这个集合只能存储这种类型
ArrayList<String> list1 = new ArrayList<String>();
list1.add("abc");
list1.add("abc");
list1.add("abc");
String s = list1.get(0); //这里直接获取就OK,不需要向下转型
泛型的好处的演示:(自定义类中使用泛型!)
  • 一般通用类型的定义方法:(拥有扩展性,但是必须使用向下转型才能使用!)
public class MyClass {
    private Object obj;

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }
}
----------------------------------------
public class MyTest {
    public static void main(String[] args) {

        //定义类时,或方法时,都想考虑这个扩展性
        MyClass myClass = new MyClass();
        myClass.setObj(100);
        Object obj = myClass.getObj();
        Integer integer= (Integer) obj; // 向下转型

        MyClass myClass1 = new MyClass();
        myClass1.setObj("abc");
        Object obj1 = myClass1.getObj();
        String string= (String) obj1;
    }
}
  • 泛型定义方法:(既拥有了扩展性,同时也避免了向下转型!)
public class MyDem<T> { //T 泛型(在类中定义!)
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}
-----------------------------
public class MyTest {
    public static void main(String[] args) {
        //设计一个类,既要扩展性,也不想向下转型。
        //设计一个泛型类,给类加上泛型
        //class A<T>{}
        //泛型机制:是JDK1.5引入的,是一种将数据类型明确工作,推迟到创建对象,或调用方法时,再去明确的一种机制。
        MyDem<String> myDem = new MyDem<>(); 由于前面已经声明了泛型的指代为:String,后面的<>中的泛型指定可以省略。
        myDem.setObj("abc");
        String obj = myDem.getObj();
        System.out.println(obj);
		//如不注明,则说明:泛型为Object!
        MyDem<Integer> integerMyDem = new MyDem<>();
        integerMyDem.setObj(200);
        Integer obj1 = integerMyDem.getObj();
        new ArrayList<Integer>(); //指明了ArrayList中泛型为:Integer,则ArrayList中只能存储Integer类型的数据。
    }
}
多泛型的使用:
  • 示例:(定义泛型的类)
public class MyHaHa<R,P>{ //多泛型
    private R r;
    private P p;

}
  • 示例:(主函数)
public class MyTest {
    public static void main(String[] args) {
        MyHaHa<Integer, String> integerStringMyHaHa = new MyHaHa<>(); //多泛型的使用!
       // integerStringMyHaHa.set("string");

        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(100);
        integers.add(100);
        integers.add(100);
        integers.add(100);
        integers.add(100);
        integers.add(100);
        integers.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        });
    }
}
----
输出:
100
100
100
100
100
100
泛型接口的概述和使用
  • 接口上的泛型都是在定义实现其子类的过程中传入的!
  • 示例:(主函数中利用匿名内部类来实现接口的子类)
public class MyTest {
    public static void main(String[] args) {
        //泛型接口 什么时候去明确
        //匿名内部类
        new MyInterface<Integer,Integer>(){

            @Override
            public Integer set(Integer integer) {
                return null;
            }
        };
    }
}
  • 示例:(接口)
interface MyInterface<T,R>{   //在接口上使用泛型
    R set(T t);
}
  • 示例:(实现接口的子类)
//子类在实现接口时,可以以明确接口上的泛型到底是什么类型
class Son implements MyInterface<String,Integer>{
    @Override
    public Integer set(String s) {
        return null;
    }
}
泛型在方法上的使用:
  • 示例:(自定义类)
class AA{
	原来的办法:(为了考虑通用性)
   /* public void set(Object str) {
        System.out.println(str);
    }*/

   	泛型方法
    public<P> void set(P str) {

        System.out.println(str);
    }
}
  • 主函数:
public class MyTest {
    public static void main(String[] args) {
        //方法上的泛型,在你调用方法时,再去明确
        AA aa = new AA();
        aa.set(3.14); //这里没有专门指定泛型的语法,确也可以(神奇!!!!)
        aa.set(200);
        aa.set("abc");
    }
}
  • 泛型一般在类和接口上使用的比较多!
泛型高级之通配符:
  • 泛型通配符<?>:
    任意类型,如果没有明确,那么就是Object以及任意的Java类了
  • 泛型如果明确了数据类型以后,那么要求左右两边的数据类型必须一致
Collection<Object> col1 = new ArrayList<Object>() ;
Collection<Object> col2 = new ArrayList<Animal>() ; 报错(前后不一致)
  • 泛型统配符号:(前面用统配符号,后面则必须注明!)
ArrayList<?> objects2 = new ArrayList<cat>(); 这种方法就不需要前后都一致了!
  • ? extends E:向下限定,E及其子类
Collection<? extends Animal> col9 = new ArrayList<Object>() ; 报错(因为Object不是Animal的子类)
Collection<? extends Animal> col10 = new ArrayList<Animal>() ; 自己本身也可以
Collection<? extends Animal> col11 = new ArrayList<Dog>() ;
  • ? super E:向上限定,E及其父类
Collection<? super Animal> col13 = new ArrayList<Object>() ;
Collection<? super Animal> col14 = new ArrayList<Animal>() ;
Collection<? super Animal> col15 = new ArrayList<Dog>() ; 报错(因为Dog是Animal的子类而不是父类!)
  • 特别注意:泛型通配符的一些注意要点,这里面说明了这些泛型通配符在什么场景下使用,该如何使用,有哪些需要注意的坑!(非常重要!)
增强for循环:
  • 概述:主要用来简化数组和Collection集合的遍历(在JDK1.5及以后版本适用)
  • 格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
		使用变量即可,该变量就是元素
	}
  • 示例:(遍历数组)
int[] arr={20,20,30,80};
--------------------(普通for循环)
for (int i = 0; i < arr.length; i++) {
     System.out.println(arr[i]);
}
--------------------(增强for循环)
for(int i:arr){
	System.out.println(arr[i]);
}
  • 示例:(遍历集合)
ArrayList<Integer> list = new ArrayList<>();
list.add(200);
list.add(200);
list.add(200);
list.add(200);
for(Integer num:list){
    System.out.println(num);
}
  • 优点:简化了遍历的写法!
  • 特点:它的底层是用迭代器在进行迭代,所以在迭代过程中不能进行增删元素!),这一点和Python极其像!
    否则,就会报错:java.util.ConcurrentModificationException (并发修改异常!)
  • 普通for循环和增强for循环的适用特点:
    a. 如果循环过程中需要拿索引做判断,那你就使用普通for循环
    b. 如果只是遍历元素看一下,那就使用新式for循环
JAVA可变参数:
  • 可变参数概述:
    定义方法的时候不知道该定义多少个参数(如果也不知道具体类型的话,则可以使用泛型来进行指定!),可变参数(数组)中的数据类型都是一样的(是同属一个类型的数组!)
  • 格式:
修饰符 返回值类型 方法名(数据类型…  变量名){}
  • 注意:
    a. 这里的变量其实是一个数组
    b. 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
  • 示例:
public class MyTest {
    public static void main(String[] args) {
        int sum = add(1, 2);
        int sum2 = add(1, 2, 3);
        int sum3 = add(1, 2, 3, 4);
        //可变参数:一次可以接收多个参数
        System.out.println(sum);
        System.out.println(sum2);
        System.out.println(sum3);

    }

    //可变参数 数据类型 ... 参数名
    //可变参数 本质是个数组
    //如果说一个方法上,有普通参数,也有可变参数,可变参数肯定是最后一个参数
    private static int add(int b,int... num) {
        //System.out.println(num.length);
        int sum=0;
        for (int i : num) { // 增强for循环!
            sum+=i;
        }
        return sum+b;
    }
}
Arrays工具类的asList()方法的使用:
  • 概念:Arrays工具类的asList(T… t)方法的使用,将数组转换成集合。
  • 格式:
static <T> List < T > asList(T...a)
  • 示例:
public class MyTest {
    public static void main(String[] args) {
        Integer[] integers = {20, 30, 50, 60};
        如果你给该方法,传入的是一个引用类型数组,那么他会取出数组中的元素,放到集合中
        List<Integer> integers1 = Arrays.asList(integers);
        for (Integer integer : integers1) {
            System.out.println(integer);
        }
        System.out.println("=====================================");
        Integer[] integers2 = {20, 30, 50, 60};
        Integer[] integers3 = {20, 30, 50, 60};
        假如你传入两个以上的数组,他是把数组对象作为元素,放到集合中
        List<Integer[]> integers4 = Arrays.asList(integers, integers2);
        System.out.println(integers4);
        Integer integer = integers4.get(0)[0];
        System.out.println(integer);
        
        System.out.println("================");
        Integer[] integers5 = {20, 30, 50, 60};
        List<Integer> integers6 = Arrays.asList(integers5);

        int[] ints = {20, 30, 50, 60};
        当你传人一个基本类型数组,那么转换成集合,集合放到是数组对象(数组对象的指针)
        List<int[]> ints1 = Arrays.asList(ints);
        int[] ints2 = ints1.get(0);

        int[] ints3 = {20, 30, 50, 60};
        int[] ints4 = {20, 30, 50, 60};
        List<int[]> ints8 = Arrays.asList(ints3, ints4);
        System.out.println(ints8);

        List<Integer> integers7 = Arrays.asList(20, 30, 50, 30, 80); //自动装箱!
		System.out.println(integers7);
    }
}
------
输出:
20
30
50
60
=====================================
[[Ljava.lang.Integer;@1b6d3586, [Ljava.lang.Integer;@4554617c]
20(第0个元素)
================
[[I@74a14482, [I@1540e19d](List中存储的是int[]对象的地址值!)
[20, 30, 50, 30, 80]
  • 特别注意:得到的集合长度是不可变的。你不能往这个转换后的集合中添加元素(add)和删除元素(remove),只能获取元素(get)。
JAVA 嵌套集合:(ArrayList嵌套ArrayList)
  • 示例:
public class MyTest3 {
    public static void main(String[] args) {
        ArrayList<Student> javaList = new ArrayList<>();
        javaList.add(new Student("周丹", 19));
        javaList.add(new Student("周颖", 19));
        javaList.add(new Student("苏沅湘", 20));
        javaList.add(new Student("崔继宣", 19));


        ArrayList<Student> webList = new ArrayList<>();

        webList.add(new Student("周丹1", 19));
        webList.add(new Student("周颖1", 19));
        webList.add(new Student("苏沅湘1", 20));
        webList.add(new Student("崔继宣1", 19));


        ArrayList<Student> linuxList = new ArrayList<>();

        linuxList.add(new Student("周丹2", 19));
        linuxList.add(new Student("周颖2", 19));
        linuxList.add(new Student("苏沅湘2", 20));
        linuxList.add(new Student("崔继宣2", 19));

        //我站在西开的角度,我要存储这个三个班(嵌套ArrayList存储)
        ArrayList<ArrayList<Student>> westosList = new ArrayList<>();
        westosList.add(javaList);
        westosList.add(webList);
        westosList.add(linuxList);
       
        //遍历每一个班的每一个学生的信息 二维集合的遍历
        //普通for循环遍历
        for (int i = 0; i < westosList.size(); i++) {
            ArrayList<Student> minList = westosList.get(i);
            // System.out.println(minList);
            for (int j = 0; j < minList.size(); j++) {
                Student student = minList.get(j);
                System.out.println(student.getName() + "===" + student.getAge());
            }
        }
        System.out.println("=================================");
        //新式for循环遍历
        for (ArrayList<Student> students : westosList) {
            for (Student student : students) {
                System.out.println(student.getName() + "===" + student.getAge());
            }
        }
        System.out.println("======================");
    }
}
---------------
输出:
周丹===19
周颖===19
苏沅湘===20
崔继宣===19
周丹1===19
周颖1===19
苏沅湘1===20
崔继宣1===19
周丹2===19
周颖2===19
苏沅湘2===20
崔继宣2===19
=================================
周丹===19
周颖===19
苏沅湘===20
崔继宣===19
周丹1===19
周颖1===19
苏沅湘1===20
崔继宣1===19
周丹2===19
周颖2===19
苏沅湘2===20
崔继宣2===19
======================