0
点赞
收藏
分享

微信扫一扫

第十七天集合(上)

安七月读书 2022-02-14 阅读 87

  

需求:利用数组存储3个学生信息,遍历数组获取到每一个学生信息

public class Student {
    private String name;
    private int age;
public Student(){

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

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

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

}

public class ObjectArrayDemo {
    public static void main(String[] args) {
        Student[] arr = new Student[3];
        for (int i=0;i<arr.length;i++){
            System.out.println(arr[i]);
        }
        System.out.println("=====================");
        Student s1=new Student("小米",19);
        Student s2=new Student("小安静",16);
        Student s3=new Student("小b白", 59);
        //当数组中的元素是引用数据类型的时候,使用循环进行赋值是有问题的,因为对象的名字没有规律
        //没有办法在每一次的循环赋值不一样的对象
        //所以给对象数组进行赋值的时候,只能一个一个赋值
        arr[0]=s1;
        arr[1]=s2;
        arr[2]=s3;

        for (int i=0;i<arr.length;i++){
         Student student=arr[i];
            System.out.println(student.getName()+"------"+student.getAge());
        }

    }
}

在上一个案例中,假设存储完所有的学生对象后,来了一个新同学,也想放到对象数组中,直接放进去的话

长度已经是固定的,很明显没有空余的位置。那怎么办呢?按照我们之前的思路,这时候就会搞一个新的数组,长度是原来数组长度+1,然后再

挨个存放。

这时候,有一个学生,提前毕业,数组中的元素就少了一个,这时候,数组就空出来一个位置

空出来的这个位置依旧是占用内存的,也不太好,所以这时候,你又创建一个新的数组,长度是原来-1,然后挨个存放。

通过上面的分析后发现,无论是增加还是删除,对于数组而言都是非常麻烦的,原则上实际是在原先东西的基础上进行修改,而不会重新创建一个空间

想一想,我们有没有学过这么一个东西,可以根据我们存放的内容的多少,自由改变长度就好了。

我们想到了之前学过的StringBuffer,它可以根据元素的多少来改变长度。但是,StringBuffer里面存储的内容始终是一个一个的字符

而我们现在要存放一个学生对象,所以呢,用StringBuffer存储也不太合适。

这时候,我们就想不到还学过哪些容器可以根据元素的多少来改变长度。

Java替我们考虑到了这一点,可以根据元素的不用,元素的特点和存储的方式不同,提供了一个集合继承体系给我们使用,简单来说

就是今天要上的内容。

集合和数组的不同点: 1、数组的长度是不可变的,集合的长度是可变的 2、数组可以存放同一种基本数据类型或者引用数据类型的元素 而集合只能存放引用数据类型,并且集合中可以存放法不同数据类型的元素 (注意:这里我虽然说了集合可以存放不同的数据类型,实际确实也可以这么做,但是呢, 在实际开发中,一个集合存放一种引用数据类型的元素) 集合可以存放各种各样的数据,每种数据的长度,大小以及自身的特点都不一样。 所以,java提供的集合也不应该是单一的,我们要针对不同的需求,使用java提供的不同的集合。 这么多不同的集合,它们底层的数据结构也是不同的,占用的内存空间也是不一样的。不同不重要,我们只需要知道集合是可以用来 存放数据的,不光可以存放,而且可以使用这些数据,比如:查找数据,获取数据,判断数据,删除数据等等。 既然可以进行上面的操作,这些不同集合类,应该有着某种共性,所以我们根据集合的共性内容不断地向上提取,最终形成一个继承体系。 Collection:是集合中的顶层接口,它存在由它展开而来的继承体系。 至于为什么要有这么多不同的集合,根据元素是否唯一,是否有序来这么多集合(后面的课程中我们会一一学习) Collection: 由于Collection是一个接口,所以无法被实例化,我们要找它一个子类来进行接口多态的方式实例化,这里我们就暂时用ArrayList 来举例。 1、添加功能 boolean add(Object e)确保此集合包含指定的元素(可选操作) boolean addAll(Collection c) 将指定集合中的所有元素添加到此集合(可选操作) 2、删除功能 boolean remove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。 boolean removeAll(Collection c) 删除指定集合中包含的所有此集合的元素(可选操作)。 void clear() 从此集合中删除所有元素(可选操作)。 3、获取功能 Iterator iterator() 返回此集合中的元素的迭代器。 4、判断功能 boolean contains(Object o) 如果此集合包含指定的元素,则返回 true 。 boolean containsAll(Collection c) 如果此集合包含指定 集合中的所有元素,则返回true。 boolean isEmpty() 如果此集合不包含元素,则返回 true 。 5、获取长度方法: int size() 返回此集合中的元素数 6、求交集功能 boolean retainAll(Collection c) 仅保留此集合中包含在指定集合中的元素(可选操作)。 7、将集合转成数组 Object[] toArray() 返回一个包含此集合中所有元素的数组。

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

public class CollectionDemo1 {
    public static void main(String[] args) {
        Collection c=new ArrayList();
        //boolean add(Object e)确保此集合包含指定的元素(可选操作)
        System.out.println(c.add("hello"));
        System.out.println(c.add("world"));
        System.out.println(c.add("hello"));
        c.add(20);
        c.add(13.4);
        System.out.println(c);
        //void clear() 从此集合中删除所有元素(可选操作)。
//   c.clear();
        //boolean remove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
        //删除指定的元素
        //只移除一个符合条件的元素
//        System.out.println("从该集合中删除指定的元素:"+c.remove("world"));
//        System.out.println(c);
//        System.out.println("从该集合中删除指定的元素:"+c.remove("hello"));
//        System.out.println(c);//只会删除第一个与之匹配的字符
        //boolean contains(Object o) 如果此集合包含指定的元素,则返回 true 。
        //判断该集合中是否包含某个元素,如果包含,返回true
        System.out.println(c.contains("hello"));
        //boolean isEmpty() 如果此集合不包含元素,则返回 true 。
        System.out.println(c.isEmpty());
        System.out.println("集合的长度为:"+c.size());
        /**
         * java.lang.Object
         *      java.util.AbstractCollection<E>
         *              java.util.AbstractList<E>
         *                      java.util.ArrayList<E>
         */
        System.out.println(c); //这里调用的是AbstractCollection类中的toString()方法



    }
}

boolean addAll(Collection c) 将指定集合中的所有元素添加到此集合(可选操作)

boolean removeAll(Collection c) 删除指定集合中包含的所有此集合的元素(可选操作)。

boolean containsAll(Collection c) 如果此集合包含指定 集合中的所有元素,则返回true。

boolean retainAll(Collection c) 仅保留此集合中包含在指定集合中的元素(可选操作)。

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

public class CollectionDemo2 {
    public static void main(String[] args) {
        Collection c1 = new ArrayList();
        c1.add("hello");
        c1.add("world");
        c1.add("java");
        c1.add("hadoop");
        c1.add("hive");
        c1.add("spark");
        Collection c2 = new ArrayList();
        c2.add("小米");
        c2.add("休假");
        c2.add("空洞");
        System.out.println("c1:" + c1);
        System.out.println("c2:" + c2);
        System.out.println("=========================================");
        System.out.println(c1.retainAll(c2));
        System.out.println("c1:" + c1);
        System.out.println("c2:" + c2);

    }
}

集合的遍历:目的就是将集合中的元素依次取出来

Object[] toArray() 返回一个包含此集合中所有元素的数组。

将集合转化成数组,然后再遍历

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

public class CollectDemo3 {
    public static void main(String[] args) {
        Collection c=new ArrayList();
        c.add("hello");
        c.add("world");
        c.add("java");
        c.add("hadoop");
        c.add("hive");
        //Object[] toArray() 返回一个包含此集合中所有元素的数组。
        Object[] objects = c.toArray();
        for (int i=0;i<objects.length;i++){
            System.out.println(objects[i]);
            //需求:想要获取每一个字符串元素的长度?
//   System.out.println(objects[i].length());
            //因为获取到的元素是由Object类型接收的,实际是String类型
            //这样就形成了多态
            //而多态调用成员方法,编译看左,运行看右
            //Object类中没有length()方法,所以报错
            //要想使用子类中特有的方法,就要向下转型
            String s=(String) objects[i];
            System.out.println(s+"------"+s.length());
        }
    }
}

需求:向集合中添加3个学生对象,并遍历学生学生信息

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

public class CollectionDemo4 {
    public static void main(String[] args) {
        //创建集合对象
        Collection c = new ArrayList();

        //创建3个学生对象
        Student s1 = new Student("明旺", 18);
        Student s2 = new Student("王宇", 17);
        Student s3 = new Student("周家祥", 16);

        //将学生对象添加到集合中
        c.add(s1);
        c.add(s2);
        c.add(s3);
        //将学生对象添加到集合中
        Object[] objects = c.toArray();
for (int i=0;i<objects.length;i++){
    System.out.println(objects[i]);//输出地址值
    //向下转型,转成元素的类型
    Student s=(Student) objects[i];
    System.out.println(s.getName()+"------"+s.getAge());
}
    }
}

Iterator iterator() 返回此集合中的元素的迭代器。 它是Collection集合遍历的专有方式

boolean hasNext() 判断迭代器中是否还有元素

Object next() 返回迭代器中的元素

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

public class CollectionDemo5 {
    public static void main(String[] args) {
        //创建一个集合对象
        Collection c = new ArrayList();
        //向集合中添加元素
        c.add("hello");
        c.add("world");
        c.add("java");
        c.add("hadoop");
        c.add("hive");
//        System.out.println(c);
        //获取集合c的迭代器对象
        //Iterator iterator() 返回此集合中的元素的迭代器。  它是Collection集合遍历的专有方式
        Iterator iterator = c.iterator(); // Iterator iterator = new Itr();这里查看源码
//        System.out.println(iterator);//java.util.ArrayList$Itr@4554617c
//        Object next = iterator.next();
//        System.out.println(next);
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());会报错
        //当我们多调用了一次next方法的时候,报错了
        //原因是,我们发现在调用之前,迭代器中的元素就已经遍历完了,不应该再指向下一个,是多余的
        //如何解决呢?实际上我们应该在获取元素之前判断一下下一个位置是否有元素,如果有元素,我们就调用next方法获取
        //如何去判断呢
        //boolean hasNext() 判断迭代器中是否还有元素
//        if (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
//        if (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
//        if (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
//        if (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
//        if (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
//        if (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
//        if (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }//多写一个不会报错
        //通过加入判断后我们发现,虽然代码不报错,并且也可以正确的将结果打印出来
        //但是,我们并不知道什么时候遍历到迭代器中的最后一个元素
        //怎么改进?循环改进
        //由于我们不知道要循环多少次,所以我们采用while循环
        while (iterator.hasNext()){
            Object next = iterator.next();
            //向下转型使用元素数据类型特有的方法
            String s=(String) next;
//     System.out.println(iterator.next());
       System.out.println(s + "--长度为:" + s.length());

        }
    }
}

1、能否将while循环改成for循环呢? 能,但是不推荐,在工作中推荐使用while循环

同一个迭代器只能遍历一次,多次遍历没有效果,因为遍历一次后,指针指向末尾。

2、Java为什么要将Iterator定义成一个接口呢?而不是一个类呢?

将来你需要根据不同的数据创建不同的集合去存储,每个集合都有自身特点,很有可能每一个集合遍历的顺序和方式都不一样

所以将来取值的时候,使用的方式也不一定是一样的,所以迭代器不应该直接实现如何遍历,而是提供一个接口

将来特有的集合类去实现这个接口中的取值方法,来实现自身的取值特点。

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

public class CollectionDemo6 {
    public static void main(String[] args) {
        Collection c=new ArrayList();
        //创建3个学生对象
        Student s1 = new Student("小明", 18);
        Student s2 = new Student("小红", 17);
        Student s3 = new Student("小白", 16);
        c.add(s1);
        c.add(s2);
        c.add(s3);
        Iterator iterator = c.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            Student s=(Student) next;
            System.out.println(s.getName() + "---" + s.getAge());
        }
//        System.out.println(iterator.next());//会报错
        System.out.println("============用普通for循环遍历(不推荐)=========================");
        for (Iterator iterator1 = c.iterator(); iterator1.hasNext(); ){
            Object next = iterator1.next();
            Student s=(Student) next;
            System.out.println(s.getName() + "---" + s.getAge());

        }
    }
}

存储字符串并遍历

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

public class CollectionTest1 {
    public static void main(String[] args) {
        //1、创建集合对象
        Collection c = new ArrayList();

        //2、添加元素到集合中
        c.add("hello");
        c.add("world");
        c.add("java");
        c.add("bigdata");
        c.add("hive");
        //3、遍历
        Object[] objects = c.toArray();
        for (int i = 0; i < objects.length; i++){
            String s=(String) objects[i];
            System.out.println(s + ",字符串的长度为:" + s.length());

        }
        System.out.println("=================================================");
        //迭代器遍历
        //获取集合的迭代器对象
        Iterator iterator = c.iterator();
        while (iterator.hasNext()){
            String s=(String) iterator.next();
            System.out.println(s + ",字符串的长度为:" + s.length());
        }
    }
}

存储自定义对象并遍历

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

public class CollectionTest23 {
    public static void main(String[] args) {
        Collection c=new ArrayList();
        Student s1 = new Student("张飞", 17);
        Student s2 = new Student("关羽", 18);
        Student s3 = new Student("赵云", 19);
        Student s4 = new Student("黄忠", 20);
        Student s5 = new Student("马超", 21);
        c.add(s1);
        c.add(s2);
        c.add(s3);
        c.add(s4);
        c.add(s5);
        //4、遍历集合
        //获取迭代器对象
        Iterator iterator = c.iterator();
        while (iterator.hasNext()){
            Student student=(Student) iterator.next();
            System.out.println(student.getName() + "---" + student.getAge());
        }
    }
}

list

List接口(继承自Collection接口) 1、List集合中的元素是有序的(存储和取出顺序一致) 1,2,3,4,5 ---> 1,2,3,4,5 2、List集合包含了索引的概念 3、List集合中的元素是可以重复的 1,1,2,3,4,4,5

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

public class ListDemo1 {
    public static void main(String[] args) {
        List list=new ArrayList();
        //向集合中添加元素
        list.add("hello");
        list.add("world");
        list.add("bigdata");
        list.add("java");
        //遍历
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            String s=(String) iterator.next();
            System.out.println(s + ",字符串的长度为:" + s.length());
        }
    }
}

List相关集合特有的功能:

因为List集合拥有下标索引的概念,所以根据这个索引衍生出特有方法

1、添加功能:

void add(int index, Object element) 将指定的元素插入此列表中的指定位置(可选操作)。

2、删除功能:

Object remove(int index) 删除该列表中指定位置的元素(可选操作)。

3、获取功能:

Object get(int index) 返回此列表中指定位置的元素。

4、修改功能:

Object set(int index, Object element) 用指定的元素(可选操作)替换此列表中指定位置的元素。

5、List集合特有的迭代器

ListIterator listIterator() 返回列表中的列表迭代器(按适当的顺序)。

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

public class ListDemo2 {
    public static void main(String[] args) {
    List list=new ArrayList();
     list.add("hello");
        list.add("world");
        list.add("java");
        list.add("bigdata");
        list.add("hadoop");
        System.out.println(list);
        System.out.println("======================================");
        //void add(int index, Object element) 将指定的元素插入此列表中的指定位置(可选操作)。
//        //超出的范围:index < 0 || index > size() ===>  0<=index<=size()  ===>  [0,size()]
        list.add(0,"hive");
        System.out.println(list);
        list.add(6,"hbase");
        System.out.println(list);
//        list.add(10,"hbase");
//        System.out.println(list);会报错
        System.out.println("======================================");
        //Object remove(int index) 删除该列表中指定位置的元素(可选操作)。
        System.out.println(list.remove(3));
        System.out.println(list);
        System.out.println("======================================");
//        //Object get(int index) 返回此列表中指定位置的元素。
        System.out.println(list.get(5));
        System.out.println(list);
        System.out.println("======================================");
        //Object set(int index, Object element) 用指定的元素(可选操作)替换此列表中指定位置的元素
        Object obj = list.set(2, "good");
        System.out.println(obj);
        System.out.println(list);
    }
}

List集合特有的迭代器

ListIterator listIterator() 返回列表中的列表迭代器(按适当的顺序)。

public interface ListIterator extends Iterator

由于ListIterator继承自Iterator接口,所以内部一定有hasNext()和next()方法

Object previous() 返回列表中的上一个元素,并向后移动光标位置。 返回列表中的上一个元素,并向后移动光标位置。 可以反复调用此方法以向后方遍历列表,或者与调用next()进行混合来回。 1、该方法是获取集合中前一个元素 2、该方法获取元素的指针与next()获取元素的指针是同一个 注意:要想倒着遍历,就必须先正着遍历,先将指针移动到末尾。在开发中不常用,但是在面试中可能会问到。 boolean hasPrevious() 返回 true如果遍历反向列表,列表迭代器有多个元素。 判断上一个位置是否有元素,如果有元素返回true,如果没有元素,返回false。

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

public class ListDemo3 {
    public static void main(String[] args) {
        //1、创建List集合对象
        List list = new ArrayList();

        //2、添加元素到集合中
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("bigdata");
        //3、遍历
        ListIterator listIterator1 = list.listIterator();
        while (listIterator1.hasNext()) {
            String s = (String) listIterator1.next();
            System.out.println(s + "字符串长度为:" + s.length());

        }
        while (listIterator1.hasPrevious()) {
            Object previous = listIterator1.previous();
            System.out.println(previous);
        }


    }

}

List集合特有的遍历方式:size()与get()方法结合使用

List集合遍历的方式: 1、调用toArray()方法,转成数组遍历 2、迭代器遍历 3、size()与get()方法结合使用遍历

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

public class ListDEMO4 {
    public static void main(String[] args) {
        //1、创建List集合对象
        List list = new ArrayList();

        //2、向集合中添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("bigdata");
        list.add("hadoop");

        //size()与get()方法结合使用遍历集合
        for (int i=0;i< list.size();i++){
            Object o = list.get(i);
            //向下转型
            String s = (String) o;
            System.out.println();
            System.out.println(s + ",字符串的长度为:" + s.length());
        }
    }
}

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

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

public class ListDemo5 {
    public static void main(String[] args) {
        //1、创建List集合对象
        List list = new ArrayList();

        //2、创建学生对象
        Student s1 = new Student("小明", 18);
        Student s2 = new Student("小康", 19);
        Student s3 = new Student("小组", 20);
        Student s4 = new Student("小的", 17);
        //3、将学生对象添加到集合中
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        //遍历
        //a:转成数组遍历
        Object[] objects = list.toArray();
        for (int i=0;i< objects.length;i++){
            Student s=(Student) objects[i];
            System.out.println(s.getName() + "---" + s.getAge());
        }
        System.out.println("=======================================");
        //b:迭代器遍历
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            Student s=(Student)iterator.next();
            System.out.println(s.getName() + "---" + s.getAge());
        }
        System.out.println("=======================================");
        //c:get()和size()方法结合遍历(这是List集合特有的遍历方式,因为有索引的概念)
        for (int i=0;i< list.size();i++){
            Student s=(Student)list.get(i);
            System.out.println(s.getName() + "---" + s.getAge());
        }
    }
}

需求:有一个集合,集合中存储着一些字符串类型的元素,我想判断一下里面有没有"bigdata"这个字符串

如果有,我们就添加一个"yes"。

ConcurrentModificationException: 并发修改异常 当不允许这样的修改的时候,java就检测到该对象出现了并发修改异常。 原因: 迭代器是依赖于集合而存在的,在遍历迭代器中的元素的时候,当我们判断成功后,往集合中添加一个元素,但是呢 这时候,迭代器并不知道已经添加了元素,所以就报错了。 简单描述:在迭代器遍历的时候,不能通过集合去修改元素 解决办法: 1、迭代器遍历,迭代器修改 2、集合遍历,集合修改

举报

相关推荐

0 条评论