JavaSE——Day15——对象数组,集合类

文章目录

  • 对象数组的概述和使用
  • 集合的由来及集合继承体系图
    • 数组和集合的区别
    • 集合继承体系图
  • Collection集合的功能概述
    • Collection集合的基本功能测试
    • Collection集合的高级功能测试
    • 集合的遍历之转化成数组遍历
    • 集合的遍历之迭代器遍历
  • Collection存储自定义对象并遍历
  • 迭代器的原理及源码解析
  • List概述及特点
    • List集合的特有功能概述和测试
    • List集合的特有遍历功能(双向迭代)
    • List集合存储学生对象并遍历
    • 并发修改异常产生的原因及解决方案
  • List的三个子类的特点

对象数组的概述和使用

先来看一个案例,这个案例用来演示利用数组存储学生信息并遍历输出。

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 09:58
 * @Description: TODO
 * A:案例演示
 * 需求:我有3个学生,请把这个3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。
 * 学生:Student
 * 成员变量:name,age
 * 构造方法:无参,带参
 * 成员方法:getXxx()/setXxx()
 */
public class Demo1 {
    public static void main(String[] args) {
        //    创建三个学生
        Student s1 = new Student("张三", 19);
        Student s2 = new Student("李四", 29);
        Student s3 = new Student("王五", 39);
        //    创建一个用来存储学生的数组
        Student[] students = new Student[3];
        students[0] = s1;
        students[1] = s2;
        students[2] = s3;
        //    遍历数组
        for (Student s : students) {
            System.out.println("姓名是:" + s.getName() + "   年龄是:" + s.getAge());
        }
    }
}

//首先来创建学生类
class Student {
    private String name;
    private int 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;
    }

    public Student() {

    }

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

思考:数组作为容器,可以存储基本数据类型元素,也可以存储引用类型元素。可是我们都知道,引用类型存储的只能是对象,我们明显感觉到利用数组来操作对象不是很方便。为了方便对多个对象的操作,java给我们提供了集合类。

集合的由来及集合继承体系图

上述已经提到,面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,Java给我们提供了集合类。那么数组和集合有什么区别呢?

数组和集合的区别

  • 长度区别:数组的长度是固定的,而集合的长度是可变的
  • 存储数据类型的区别:数组可以存储基本数据类型,也可以存储引用数据类型;集合只能村存储引用数据类型
  • 内容区别:数组只能存储同种数据类型的元素,而集合可以存储不同类型的元素。

集合继承体系图

JavaSE——Day15——对象数组,集合类_第1张图片

Collection集合的功能概述

  • a:添加功能
boolean add(Object obj):
添加一个元素
boolean addAll(Collection c):
添加一个集合的元素  (给一个集合添加进另一个集合中的所有元素)
  • b:删除功能
void clear():
移除所有元素
boolean remove(Object o):
移除一个元素
boolean removeAll(Collection c):
移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素 
如果没有交集元素 则删除失败 返回false
  • c:判断功能
boolean contains(Object o):
判断集合中是否包含指定的元素	
boolean containsAll(Collection c):
判断集合中是否包含指定的集合元素(这个集合 包含 另一个集合中所有的元素才算包含 才返回true)
比如:123 containsAll 12=true   1,2,3 containsAll 2,3,4=false
boolean isEmpty():
判断集合是否为空
  • d:获取功能
Iterator<E> iterator()(重点)
  • e:长度功能
int size():元素的个数
  • f:交集功能
boolean retainAll(Collection c):
获取两个集合的交集元素(交集:两个集合都有的元素)
例如:A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化
  • g:把集合转换为数组
Object[] toArray()

Collection集合的基本功能测试

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

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 10:52
 * @Description: TODO
 * 集合类的基本功能测试
 * boolean add(E e)
 * boolean remove(Object o)
 * void clear()
 * boolean contains(Object o)
 * boolean isEmpty()
 * int size()
 */
public class Demo2 {
    public static void main(String[] args) {
        //首先来创建一个集合
        Collection collection = new ArrayList();//多态

        //添加元素的方法:add() 返回值可以用来判断是否添加成功
        collection.add("张三");
        collection.add("李四");
        collection.add("王五");
        collection.add("赵六");
        System.out.println(collection);
        //[张三, 李四, 王五, 赵六]
        boolean b = collection.add("鬼脚七");
        System.out.println(b);//true
        System.out.println(collection);
        //[张三, 李四, 王五, 赵六, 鬼脚七]
        System.out.println("----------------------------");

        /*boolean addAll(Collection c):
          添加一个集合的元素  (给一个集合添加进另一个集合中的所有元素)*/
        Collection collection2 = new ArrayList();
        boolean b1 = collection2.addAll(collection);
        System.out.println(b1);//true
        System.out.println(collection2);
        System.out.println("----------------------------");

        /*删除:boolean remove(Object o) 返回值可以用来判断是否删除成功*/
        boolean b2 = collection.remove("鬼脚七");
        //collection.remove(4); 也可以通过索引来删除
        /*void clear():移除所有元素*/
        collection.clear();
        System.out.println("----------------------------");

        /* boolean removeAll(Collection c):
         * 移除一个集合的元素(移除一个以上返回的就是true)
         * 删除的元素是两个集合的交集元素
         * 如果没有交集元素 则删除失败 返回false*/
        Collection collection3 = new ArrayList();
        Collection collection4 = new ArrayList();
        collection3.add("1");
        collection3.add("2");
        collection3.add("3");
        collection4.add("2");
        collection4.add("3");
        System.out.println(collection3);//[1, 2, 3]
        System.out.println(collection4);//[2, 3]
        boolean b3 = collection3.removeAll(collection4);
        System.out.println(b3);//true
        System.out.println(collection3);//[1]
        System.out.println(collection4);//[2, 3]
        System.out.println("----------------------------");

        //    集合可以存储多种数据类型
        Collection collection5 = new ArrayList();
        collection5.add(10);
        collection5.add(100);
        collection5.add("abc");
        //    size()可以获取集合的大小
        int size = collection5.size();
        System.out.println(size); //3
        //    isEmpty()方法可以判断这个集合是否是空集合
        collection5.clear();
        System.out.println(collection5.isEmpty());//true
        //    boolean contains(Object o):判断集合中是否包含指定的元素
        collection5.add(1);
        collection5.add(2);
        collection5.add(3);
        boolean contains = collection5.contains(3);
        System.out.println(contains);
        //    boolean containsAll(Collection c):判断集合中是否包含指定的集合元素
        Collection collection6 = new ArrayList();
        collection6.add(1);
        collection6.add(2);
        collection5.containsAll(collection6);//true
    }
}

Collection集合的高级功能测试

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

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 14:24
 * @Description: TODO
 * A集合retainAll(B集合); 取交集,A集合最后只保留交集元素
 */
public class Demo3 {
    public static void main(String[] args) {
        Collection collection = new ArrayList();
        Collection collection1 = new ArrayList();
        collection.add(1);
        collection.add(2);
        collection.add(3);
        collection.add(4);
        collection1.add(1);
        collection1.add(5);
        collection1.add(6);
        boolean b = collection.retainAll(collection1);
        System.out.println(b);
        System.out.println(collection);
        System.out.println(collection1);
        //true
        //[1]
        //[1, 5, 6]
    }
}

集合的遍历之转化成数组遍历

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

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 14:31
 * @Description: TODO
 *
 */
public class Demo3_1 {
    public static void main(String[] args) {
        Collection collection = new ArrayList();
        collection.add(1);
        collection.add(2);
        collection.add(3);
        collection.add(4);
        //把集合转换成数组
        Object[] objects = collection.toArray();
        for (int i = 0; i < objects.length; i++) {
            //System.out.println(objects[i]);
            Integer integer = (Integer) objects[i];
            int i1 = integer.intValue();
            System.out.println(i1);
        }
    }
}

集合的遍历之迭代器遍历

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

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 14:37
 * @Description: TODO
 * 案例演示:		迭代器的使用
 * boolean hasNext ()
 * 如果仍有元素可以迭代,则返回 true。
 * E next ()
 * 返回迭代的下一个元素。
 */
public class Demo4 {
    public static void main(String[] args) {
        Collection collection = new ArrayList();
        collection.add(1);
        collection.add(2);
        collection.add(3);
        collection.add(4);
        collection.add(5);
        //    获取迭代器
        Iterator iterator = collection.iterator();
        //人为移动指针
        //System.out.println(iterator.next());//1
        //System.out.println(iterator.next());//2
    //    使用迭代器遍历集合
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

Collection存储自定义对象并遍历

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

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 15:27
 * @Description: TODO
 * Collection存储自定义对象并用迭代器遍历
 */
public class Demo5 {
    public static void main(String[] args) {
        Collection collection = new ArrayList();
        collection.add(new Teacher("钢铁侠",20));
        collection.add(new Teacher("绿巨人", 20));
        collection.add(new Teacher("美国队长", 20));
        Iterator iterator = collection.iterator();
        while(iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj.toString());
        }
        /*Teacher{name='钢铁侠', age=20}
          Teacher{name='绿巨人', age=20}
          Teacher{name='美国队长', age=20}*/
    }
}

class Teacher {
    private String name;
    private int age;

    public Teacher() {
    }

    public Teacher(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 "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

迭代器的原理及源码解析

Iterator(迭代器)是集合输出操作中最为常用的接口,而在Collection接口中也提供了直接为Iterator接口实例化的方法(iterator(),所以在任何集合类型都可以转换为Iterator接口输出
所谓迭代器就好比排队点名一样,从前往后开始,一边判断是否有人,一边进行操作。
Iterator接口中定义了两个方法,hasNext()和next()方法,前者用来判断是否还有内容,后者用来取出当前内容。
实际上Scanner类也是Iterator接口的子类(想想Scanner类中的hasNextXxx()和nextXxx())。

A:迭代器原理: 为什么迭代器不定义成一个类 , 而是定义成一个接口?

我们试想一下,如果Iterator迭代器是一个类。那么我们就可以直接创建一个迭代器,并且使用它的遍历方法了,这样是不是很方便? 但是呢,Java给我们提供了很多不同的集合类,然而这些不同的集合都有不同的数据结构。所以,它们的存储方式和遍历的方式也应该是不同的。
无论是哪种集合,我们都应该具备相应的获取元素的功能(Iterator.next()),并且,最好配合一个辅助判断的功能方法(Iterator.hasNext()),这样在获取集合元素前进行判断是否有元素在集合中,更利于操作。于是java定义一个接口去定义这两个方法,这样,所有实现了这个接口的集合类都可以使用迭代器。
那么,真正的具体的实现类在哪里呢
当然是在具体的子类中实现了,具体看源码:

B:迭代器源码解析

 迭代器接口
public interface Iterator {   
boolean hasNext();
Object next();
 }

获取迭代器的接口
public interface Iterable {
    Iterator iterator();
}

Collection继承了获取迭代器接口的接口
public interface Collection extends Iterable { 
  Iterator iterator();  
}

 List接口,继承了Collection接口,并继承了获取迭代器的抽象方法
  public interface List extends Collection {
Iterator iterator();
 }

ArrayList具体的实现接口类,实现了获取Iterator的功能方法
public class ArrayList implements List { 
public Iterator iterator() {
    return new Itr();
  }


Itr是Iterator的具体实现类,在ArrayList以内部类的形式
 并且实现了Iterator的功能方法:hasNext()next(),remove()
private class Itr implements Iterator {
    public boolean hasNext() {}       
    public Object next(){} 
    }
}

Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
Iterator it = c.iterator();  //实际是获取到了一个ArrayList的内部类new Itr();
while(it.hasNext()) {
String s = (String)it.next();
System.out.println(s);
}

List概述及特点

元素有序,并且每一个元素都存在一个索引.元素可以重复.

List集合的特有功能概述和测试

List集合的特有功能概述:

  • void add(int index,E element): 在指定索引处添加元素
  • E remove(int index):移除指定索引处的元素 返回的是移除的元素
  • E get(int index):获取指定索引处的元素
  • E set(int index,E element):更改指定索引处的元素 返回的而是被替换的元素
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 19:28
 * @Description: TODO
 * 

* A:List集合的特有功能概述 * void add(int index,E element): 在指定索引处添加元素 * E remove(int index):移除指定索引处的元素 返回的是移除的元素 * E get(int index):获取指定索引处的元素 * E set(int index,E element):更改指定索引处的元素 返回的而是被替换的元素 * B:案例演示: 特有功能测试 */ public class Demo6 { public static void main(String[] args) { List list = new ArrayList(); list.add(100); list.add(200); list.add(300); list.add(0, 500); // 在指定的索引出添加元素,原索引处的元素不会被覆盖,而是朝后位移 System.out.println(list); //[500, 100, 200, 300] //通过索引来删除元素 //E remove(int index):移除指定索引处的元素 返回的是移除的元素 list.remove(0); System.out.println(list); //[100, 200, 300] //可是如果我想要直接删除100这个元素,传参的时候就要把100包装成Integer的实例,否则就会默认为删除索引为100的元素 list.remove(Integer.valueOf(100)); System.out.println(list); //[200, 300] //获取指定索引处的元素: E get ( int index) Object o = list.get(0); Object o1 = list.get(1); System.out.println(o);//200 System.out.println(o1);//300 //更改指定索引处的元素 返回的而是被替换的元素:E set(int index,E element) Object set = list.set(0, 100); System.out.println(set); //200 System.out.println(list); //[100, 300] } }

List集合的特有遍历功能(双向迭代)

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

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 20:00
 * @Description: TODO
 * A:案例演示: 使用for循环	通过size()和get()方法结合使用遍历。
 */
public class Demo6_1 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        list.add("abc5");
        //现在我们来尝试遍历这个list集合

        //方法1——使用父接口中的迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //方法2——List 集合中的迭代器
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
            System.out.println(listIterator.next());
        }

        //方法3——采用for循环
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        
		//还有一个很有意思的功能:反向遍历,这是ListIterator(双向迭代)的特有功能
        //需要注意指针的位置,前面我们已经进行了正向遍历,指针的位置就在最后
        //注意使用同一迭代器,如果不是同一迭代器,反向遍历没有效果
        while (listIterator.hasPrevious()){
            System.out.println(listIterator.previous());
        }
    }
}

List集合存储学生对象并遍历

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

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 20:44
 * @Description: TODO
 */
public class Dmeo6_2 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new Student("张三",19));
        list.add(new Student("李四", 20));
        list.add(new Student("王五", 21));
        list.add(new Student("赵六", 22));
        list.add(new Student("鬼脚七", 23));

        //遍历1 采用父接口中的迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next().toString());
        }
        System.out.println("----------------------------");

        //遍历2 采用list中的迭代器
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
            System.out.println(listIterator.next().toString());
        }
        System.out.println("----------------------------");

        //遍历3 for循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i).toString());
        }

    }
}

并发修改异常产生的原因及解决方案

  • A:案例演示
  • 需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
  • B:ConcurrentModificationException出现
  • 我们用Iterator这个迭代器遍历采用hasNext方法和next方法,集合修改集合 会出现并发修改异常
  • C:解决方案 我们用ListIterator迭代器遍历 用迭代器自带的add方法添加元素 那就不会报错了
  • a:迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add)
  • b:集合遍历元素,集合修改元素
  • 解决方案2 使用for循环遍历集合 添加元素 不会报错
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-07 21:24
 * @Description: TODO
 */
public class Demo7 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("PHP");
        list.add("Linux");
        list.add("Hello");
        list.add("world");
        //思路是遍历集合,只要发现world,就往里面加javaee
        /*
        ListIterator listIterator = list.listIterator();
        while(listIterator.hasNext()){
            if (listIterator.next()=="world"){
                list.add("javaee");
            }
        }
        */
       
        //我们的思路并没有错,但是这里一旦运行就会报错
        //ConcurrentModificationException  并发修改异常
        //产生这个异常的原因是当我们创建好一个集合后,然后去使用迭代器
        // 这个时候集合中的元素对于迭代器来说是相对固定的
        // 迭代器中所有的操作都是针对这些元素
        // 冒然的往集合里面添加元素就会使迭代器产生异常
        // 但是如果不能往里面添加元素又显然不太人性化
        // 如果要添加元素就必须使用迭代器自带的方法listIterator.add()
        // 把上述代码稍稍修改就不会报错了
        ListIterator listIterator = list.listIterator();

        while (listIterator.hasNext()) {
            if (listIterator.next() == "world") {
                listIterator.add("javaee");
            }
        }
        System.out.println(list);
        //[PHP, Linux, Hello, world, javaee]
        
        //当然我们也可以使用for循环来完成这个功能
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i)=="world"){
                list.add("javaee");
            }
        }
        
        //if(list.contains("world")){
        //    list.add("javaee");
        //}
    }

List的三个子类的特点

  • ArrayList:
    底层数据结构是数组,查询快,增删慢。
    线程不安全,效率高。
  • Vector:
    底层数据结构是数组,查询快,增删慢。
    线程安全,效率低。
  • LinkedList:
    底层数据结构是链表,查询慢,增删快。
    线程不安全,效率高。

你可能感兴趣的:(JavaSE,对象数组,集合类,迭代器)