Java 集合(一)

阅读 54

2022-04-13

集合

1,集合的引入

集合和数组都是对多个数据进行存储操作的结构,都是Java容器
说明:此时的存储,主要是指内存层面的存储,不涉及持久化的存储(如硬盘)
在这里插入图片描述

2,集合的两种体系简介

在这里插入图片描述其中:
一,Collection接口中的:
①List子接口:存储有序的、可重复的数据。–>类似“动态”数组
②Set子接口:存储无序的、不可重复的数据。–>类似高中讲的集合(无序性、确定性、互异性)


二,Map接口:存储一对(key-value)数据。类似函数:y=f(x),
一个key不可对应多个value,但不同的key可以对应同一个value。


3, 集合体系一:Collection接口

在这里插入图片描述

3.1,Collection接口中的常用方法:

以下列举了Collectin接口中定义的14种方法的使用:


①首先自定义一个Person类:

package com.atguigu.java;

import java.util.Objects;

//Person为一个自定义类
public class Person {
    private String name;
    private int age;

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

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

② 演示Collection中的14种方法

package com.atguigu.java;
import org.junit.Test;
import java.util.*;
/**
 * Collection接口:
 *              ①List接口:存储有序的、可重复的数据。-->类似“动态”数组
 *                      List接口的主要实现类:ArrayList、Linkedlist、Vector。
 *              ②Set接口:存储无序的、不可重复的数据。-->类似高中讲的集合(无序性、确定性、互异性)
 *                      Set接口主要实现类:HashSet、LinkedHashSet、TreeHashSet
 *  Map接口:双列集合,存储一对。类似函数:y=f(x),一个key不可能对应多个value,但不同的key可以对应同一个value。
 *              主要实现类:HashMap、LinkHashMap、TreeMap、Hashtable、Properties
 *
 * 由于JDK不提供此接口的任何直接实现,而是提供更具体的子接口,所以以下演示的抽象方法通过Collection的子接口(List接口)的实现类ArrayList来测试。
 */
public class CollectionTest {
    @Test
    public void test(){
        // Collection接口中的方法的使用:而这些方法都是抽象的,所以只能拿它的实现类测试
        Collection coll=new ArrayList();  //此处我们拿ArrayList实现类进行测试
        //1,add(Object e):将元素e添加到集合coll中。形参为Object型。
        coll.add("AA");  //传入Object类型的参数
        coll.add("BB");  //传入Object类型的参数
        coll.add(123);  //注意:此处由于基本数据类型123经历了自动装箱,所以可以添加进去。
        coll.add(new Date());  //传入Object类型的参数

        //2,size():获取添加的元素的个数,没有添加时为0。
        System.out.println(coll.size()); //4

        //3,addAll():将coll1集合中的元素添加到当前的集合中
        Collection coll1=new ArrayList();
        coll.add(456);
        coll.add("CC");
        coll.addAll(coll1);
        System.out.println(coll.size()); //6
        System.out.println(coll);  //可以查看具体元素。此处括号内相当于调用ArrayList实现类中重写的toString()。

        //4,isEmpty():判断当前集合是否有元素(实际是看size是否为0)
        System.out.println(coll.isEmpty());  //false

        //5,clear()清空集合元素 :执行后,对象还在,只是数据被清空
        coll.clear();
        System.out.println(coll.isEmpty()); //true

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

        Collection coll2=new ArrayList();
        coll2.add(123);
        coll2.add(456);
        coll2.add(new String("Tom"));
        coll2.add(false);   //实际变为包装类Boolean---自动装箱
        coll2.add(new Person("Jerry",20));
        //通过以下几个方法理解理解知识点:要求向Collection接口实现类的对象中添加数据数据obj时,要求obj所在类要重写equals(),我们在自定义的Person类中重写了equals()方法
        /*
        6,contains(Object obj):判断当前集合中是否包含obj。判断时会调用obj对象所在类的equals()方法。
        所以要求:向Collection接口实现类的对象中添加数据数据obj时,要求obj所在类要重写equals()
        */
        boolean contains=coll2.contains(123);
        System.out.println(contains); //true
        System.out.println(coll2.contains(new String("Tom"))); //true。此处实际调用的是equals()方法,比较内容而非地址。String中已经重写equals()
        System.out.println(coll2.contains(new Person("Jerry",20))); //true。此处实际调用的是Object类下的equals()方法,比较地址。如果自定义类Person中没有重写equals()方法,结果为false

        //7,containsAll(Collection coll3):判断形参coll3中的所有元素是否都存在于当前集合中
        Collection coll3= Arrays.asList(123,456); //实例化新方式:数组转化为集合,asList方法返回值类型为List,List又是Collection的一个子接口--(多态)
        System.out.println(coll2.containsAll(coll3));  //true

        System.out.println("*******");
        //8,remove(Object obj):从当前集合中移除obj元素。返回值类型为布尔型,表示是否移除成功。
        coll2.remove(123);  //其中也会调用equals(),先判断有无123,所以也需要重写元素所在类的equals(),123对应包装类Integer已经重写过了,此处可以移除
        System.out.println(coll2);  //[456, Tom, false, Person{name='Jerry', age=20}]。
        coll2.remove(new Person("Jerry",20)); //在自定义的Person类重写equals()后可以移除
        System.out.println(coll2);  //成功遍历

        System.out.println("**************");
        //9,removeAll(Collection coll):从当前集合中移除coll中所有元素(移除的是共有的),此方法也要调用equals()方法。
        Collection coll4=Arrays.asList(1234,456);
        coll2.removeAll(coll4); //移除共有元素 456
        System.out.println(coll2);  //[Tom, false]
    }

    @Test
    public void test1(){
        Collection coll=new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("Jerry",20));

        //10,retainAll(Collection coll1):返回布尔型,获取当前集合和coll1集合的交集元素,并返回给当前集合。
        //Collection coll1=Arrays.asList(123,456);
        //coll.retainAll(coll1);
        //System.out.println(coll); //[123, 456]。求完交集后,修改当前集合coll

        //11,equals() :判断当前集合与形参集合元素内容是否相同。
        Collection coll2=new ArrayList();
        coll2.add(123);
        coll2.add(456);
        coll2.add(new String("Tom"));
        coll2.add(false);
        coll2.add(new Person("Jerry",20));

        System.out.println(coll.equals(coll2)); //true(内容一样)。注意如果交换元素顺序,则会变为false。因为ArrayList是List接口的实现类;List接口存储有序、可重复数据
    }

    @Test
    public void test2(){
        Collection coll=new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("Jerry",20));

        //12,hashCode():返回当前对象哈希值
        System.out.println(coll.hashCode());   //700178533。类似随机数,指定存储地址

        //13,toArray():集合转换为数组
        Object[] arr = coll.toArray();
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);  //遍历数组元素
        }
        //拓展:数组也可以转化为集合。调用Arrays的静态方法---asList()
        List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});  //List属于Collection
        System.out.println(list); //[AA, BB, CC]
    }
}

特别注意:
向Collection接口实现类的对象中添加数据数据obj时,要求obj所在类要重写equals()。

3.2,Iterator接口方式遍历集合元素

第十四个方法——iterator():
返回 Iterator接口(迭代器接口) 的实例,用于遍历集合元素。

3.2.1,Iterator接口遍历集合元素

在这里插入图片描述
代码理解:

package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
 * 集合元素的遍历操作:使用迭代器Iterator接口
 */
public class IteratorTest {
    @Test
    public void test3(){
        Collection coll=new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("Jerry",20));
        //14,iterator():返回Iterator接口(迭代器接口)的实例,用于遍历集合元素
        Iterator iterator = coll.iterator();
        //方式一演示:此方法遍历较麻烦。
        //System.out.println(iterator.next());  //123
        //System.out.println(iterator.next());  //456
        //System.out.println(iterator.next());  //Tom
        //System.out.println(iterator.next());  //false
        //System.out.println(iterator.next());  //Person{name='Jerry', age=20}
        //再执行System.out.println(iterator.next())会抛异常:NoSuchElementException
        //方式二演示:使用for循环。
        //for (int i = 0; i < coll.size(); i++) {
        //    System.out.println(iterator.next());
        //}
        //方式三(推荐)演示:推荐使用hasNext()和next()搭配,开发中最常用
        while(iterator.hasNext()){  //判断还有没有元素,有则进入循环
           //next():①指针下移 ②将下移以后集合位置上的元素返回
            System.out.println(iterator.next());
        }
    }
}

在这里插入图片描述
迭代器的执行原理:

在这里插入图片描述Iterator遍历集合两种错误的写法
(根据迭代器执行原理分析错误之处):

错误写法一:

package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorTest {
    @Test
    public void test3(){
        Collection coll=new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("Jerry",20));
        Iterator iterator = coll.iterator();
        //错误写法1:
        while((iterator.next())!=null){  //此处直接调next()会往下走
            System.out.println(iterator.next()); //直接调next()会往下走
        }
    }
}

在这里插入图片描述
运行会报NoSuchElementException异常,并且会跳着输出。因为直接调next()会往下走一步。

  •  next()作用:① 指针下移 ②将下移以后集合位置上的元素返回
    

错误写法二:

package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorTest {
    @Test
    public void test3(){
        Collection coll=new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("Jerry",20));
        Iterator iterator = coll.iterator();
        //错误写法2:
        while(coll.iterator().hasNext()){  //匿名方式
            System.out.println(coll.iterator().next());   //会不断输出123
        }
    }
}

在这里插入图片描述
运行会不断输出123。原因是:集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。

3.2.2,Iterator接口的remove()方法

在这里插入图片描述

package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
 * 测试Iterator接口中的remove():可以在遍历的时候删除集合元素
 */
public class IteratorTest {
    @Test
    public void test3(){
        Collection coll=new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("Jerry",20));
        Iterator iterator = coll.iterator(); //得到迭代器对象
        //删除集合中”Tom“数据
        while (iterator.hasNext()){
            Object obj = iterator.next();//获取值。多态
            if ("Tom".equals(obj)){  //如果有”Tom“数据,进行移除
                iterator.remove();
            }
        }
        //重新遍历集合
        iterator=coll.iterator();  //上一个while循环指针已经走到头了,所以此处需要重新生成迭代器对象
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }
}

在这里插入图片描述

3.3,foreach循环方式遍历集合或数组元素

package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
/**
 * 集合的第二种遍历方式:foreach循环
 * Java 5.0 提供了 foreach 循环迭代访问 Collection和数组。
 *
 */
public class ForTest {
    @Test
    public void test1(){
        Collection coll=new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("Jerry",20));

        //for(集合中元素的类型 局部变量:集合对象)
        for(Object obj:coll){  //Object为集合中元素的类型,obj相当于我们定义的局部变量
            System.out.println(obj);
        }
    }
    //foreach遍历数组
    @Test
    public void test2(){
        int[] arr=new int[]{1,2,3,4,5,6};
        //for(数组中元素的类型 局部变量:数组对象)
        for(int i:arr){
            System.out.println(i);  
        }
    }
}

在这里插入图片描述

精彩评论(0)

0 0 举报