Java中集合的介绍(附测试代码)

目录

一、概述

二、集合框架继承树

三、集合的简单使用

 四、集合中的排序sort()

五、contains()

1. equals()

2. hashCode()

 六、举一反三

 七、最后附上完整的测试代码


一、概述

我们知道java中常常需要对多个对象进行存储和操作,而使用array数组存储对象时有一些弊端(数组中提供的属性和方法少,不便于进行添加、删除、插入等操作)。因此集合应运而生(虽然集合底层也和数组密切相关)

二、集合框架继承树

Java 集合可分为 Collection 和 Map 两种体系

Collection接口:单列数据,定义了存取一组对象的方法的集合

        List:元素有序、可重复的集合

        Set:元素无序、不可重复的集合  (无序指:不保证插入顺序,但是循环遍历时,输出顺序是不会改变的。)

Map接口:双列数据,保存具有映射关系“key-value对”的,

Map 中的 key 用Set来存放,不允许重复,同时set是元素无序、不可重复的集合,因此map,也是根据key无序、不可重复的集合

三、集合的简单使用

下面我们通过ArrayList这个最典型的集合对集合的使用进行介绍

package study01;

import java.util.*;

public class test2 {

    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();

        // 增加
        arrayList.add("aaa ");
        arrayList.add("bbb ");
        arrayList.add("ccc ");
        arrayList.add("ddd ");
        arrayList.add("ddd ");
        arrayList.add("ddd ");

        // 删除
        arrayList.remove("ddd ");

        // 输出
        System.out.println(arrayList.get(0));
        System.out.println(arrayList);

        // 迭代器操作
        Iterator<String> iterator = arrayList.iterator();

        while (iterator.hasNext()) {

            Object next = iterator.next();
            System.out.print(next);

            if (next.equals("ccc ")) {
                // 调用迭代器的remove方法
                iterator.remove();
            }
        }
        
        System.out.print("\n"+arrayList);
    }
}

 四、集合中的排序sort()

要想对集合进行排序sort,集合中的元素必须是Comparable

(ctrl + p查看方法参数)

首先我们知道sort()是一个作用于排序的方法,但不是万事万物都可以排序的(如果你想让一群自定义Dog() 对象排序,他们该以什么方式进行排序呢?),所以这需要程序员们自行定义排序的方式。

而要想让集合可以实现sort() 方法则集合中的对象必须是Comparable,因此必须满足以下条件的其中之一:

        集合中的元素必须是实现Comparable接口的类型。

        使用重载compare() 方法,取用Comparator参数的构造函数来实现排序。

下面我们选用第二种方式,因为这种方式更加灵活:

我们首先创建一个class Dog,同时创建一个内部类实现 Comparator 接口重载compare方法。再通过main方法调用sort进行测试。

package study01;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Objects;

public class Dog {

    ArrayList<Dog> arrayList = new ArrayList<>();
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }

    Dog(String name, Integer age){
        this.name = name;
        this.age = age;
    }


    // 声明一个静态内部类IdCompare 实现 Comparator 接口 用于通过age对Dog进行排序
    static class AgeCompare implements Comparator<Dog> {

        // 覆盖compare()方法,通过age排序
        @Override
        public int compare(Dog o1, Dog o2) {
            return o1.getAge().compareTo(o2.getAge());
        }
    }

    // 声明一个静态内部类NameCompare 实现 Comparator 接口
    static class NameCompare implements Comparator<Dog> {

        // 覆盖compare()方法,通过Name排序
        @Override
        public int compare(Dog o1, Dog o2) {
            return o1.getName().compareTo(o2.getName());
        }
    }


    public static void main(String[] args) {

        ArrayList<Dog> arrayList = new ArrayList<>();

        arrayList.add(new Dog("ccc ", 2));
        arrayList.add(new Dog("ddd ", 7));
        arrayList.add(new Dog("aaa ", 11));
        arrayList.add(new Dog("bbb ", 6));
        arrayList.add(new Dog("bbb ", 6));

        // 按插入顺序输出
        for (Dog a:arrayList){
            System.out.print(a.name+a.age +"\t");
        }
        System.out.println();

        // 通过 age 排序
        arrayList.sort(new AgeCompare());
        for (Dog a:arrayList){
            System.out.print(a.name+a.age +"\t");
        }
        System.out.println();


        // 通过 name 排序
        arrayList.sort(new NameCompare());
        for (Dog a:arrayList){
            System.out.print(a.name+a.age +"\t");
        }
        System.out.println();

    }
}

五、contains()

contains(a)方法用于判断集合中是否包含元素a。

要想对对象调用contains()方法就要重写equals和hashCode。因为contains()底层也通过调用equals() 和 hashCode() 判断。

1. equals()

要判断集合中是否包含就要比较集合中是否有元素相等。那么两个对象要怎样才算相等呢?

        a. 引用性相等:堆上同一对象的两个引用相等

        b. 对象相等性:堆上两个不同对象在意义上是相同的

因此这里我们要先介绍以下运算符 “==” 和 方法 equals() 

“==”:

        ①如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)

        ②如果比较的是引用数据类型变量:比较两个对象的地址值是否相同。(即两个引用是否指向同一实体)

equals() :

        ①只能适用于引用数据类型

        ②Object类中定义的equals()和==的作用是相同的。

Object类(Java中的根父类)中equals()的定义(也是通过“==”实现):

         ③通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的成员变量是否相同。那么,我们就需要对Object类中的equals()进行重写。

因此对于引用性相等我们可以用“==”判断,而对于”复杂对象在意义上相同“的判定我们可以通过重写equals()方法来实现

class Dog 重写Object 中的equals()方法:

@Override
public boolean equals(Object o) {

    // 如果引用的地址相同,那么内容肯定也相同,返回true
    if (this == o) return true;

    // 如果数据类型不同,那么对象肯定也不同,返回false
    if (!(o instanceof Dog)) return false;
    Dog user = (Dog) o;

    // 上面几行的判断只是为了提高判断效率,下面这一行这才是关键代码,不过也只是依次判断对象中各成员变量是否相同罢了
    return Objects.equals(arrayList, user.arrayList) && Objects.equals(getName(), user.getName()) && Objects.equals(getAge(), user.getAge());
}

 在main方法下测试一下:

System.out.println(arrayList.contains(new Dog("aaa ", 11)));

这里会返回true, 如果把重写的equals()方法注释掉,那么contains判断的标准变成Object 中equals()方法的引用性相等,会返回false,感兴趣的小伙伴可以试试。

2. hashCode()

hashCode()方法的存在是用来缩小寻找成本的:如果集合在对比的时候发现同样的hashcode有多个对象,那么它会使用equals() 来判断是否有完全符合。

        有 a.equals(b) 时,必有 a.hashCode() == b.hashCode()

        有 a.hashCode() == b.hashCode()时, 不一定有 a.equals(b)

@Override
public int hashCode() {
    return Objects.hash(arrayList, getName(), getAge());
}

 六、举一反三

1、要想包含Dog()对象的集合可以实现sort()方法就要让Dog类重载compare() 方法

2、要想包含Dog()对象的集合可以实现contains()方法就要让Dog类重载equals和hashCode

3、而HashSet作为一个无序不重复的集合,也就意味着它集合中的对象需要通过重载equals和hashCode方法来判断是否重复,不重载equals和hashCode的话打印出来的集合还是会重复(因为你没有制定判断重复的标准),不信你试试。

HashSet<Dog> hashSet = new HashSet<>(arrayList);
System.out.print("hashSet:\t");
for (Dog a:hashSet) {
    System.out.print(a.getName()+a.getAge()+"\t");
}
System.out.println();

4、最后讲一下map

Map 中的 key 用Set来存放,key值不允许重复,因此同hashset同理,同一个 Map 对象所对应 的类,须重写hashCode()和equals()方法

 七、最后附上完整的测试代码:

package study01;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Objects;

public class Dog {

    ArrayList<Dog> arrayList = new ArrayList<>();
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }

    Dog(String name, Integer age){
        this.name = name;
        this.age = age;
    }


    // 声明一个静态内部类IdCompare 实现 Comparator 接口
    static class AgeCompare implements Comparator<Dog> {

        // 覆盖compare()方法,通过age排序
        @Override
        public int compare(Dog o1, Dog o2) {
            return o1.getAge().compareTo(o2.getAge());
        }
    }

    // 声明一个静态内部类NameCompare 实现 Comparator 接口
    static class NameCompare implements Comparator<Dog> {

        // 覆盖compare()方法,通过Name排序
        @Override
        public int compare(Dog o1, Dog o2) {
            return o1.getName().compareTo(o2.getName());
        }
    }

    @Override
    public boolean equals(Object o) {

        // 如果引用的地址相同,那么内容肯定也相同,返回true
        if (this == o) return true;

        // 如果数据类型不同,那么对象肯定也不同,返回false
        if (!(o instanceof Dog)) return false;
        Dog user = (Dog) o;

        // 上面几行的判断只是为了提高判断效率,下面这一行这才是关键代码,不过也只是依次判断对象中各成员变量是否相同罢了
        return Objects.equals(arrayList, user.arrayList) && Objects.equals(getName(), user.getName()) && Objects.equals(getAge(), user.getAge());
    }

    @Override
    public int hashCode() {
        return Objects.hash(arrayList, getName(), getAge());
    }


    public static void main(String[] args) {

        ArrayList<Dog> arrayList = new ArrayList<>();

        arrayList.add(new Dog("ccc ", 2));
        arrayList.add(new Dog("ddd ", 7));
        arrayList.add(new Dog("aaa ", 11));
        arrayList.add(new Dog("bbb ", 6));
        arrayList.add(new Dog("bbb ", 6));

        // 按插入顺序输出
        for (Dog a:arrayList){
            System.out.print(a.name+a.age +"\t");
        }
        System.out.println();

        // 通过 age 排序
        arrayList.sort(new AgeCompare());
        for (Dog a:arrayList){
            System.out.print(a.name+a.age +"\t");
        }
        System.out.println();


        // 通过 name 排序
        arrayList.sort(new NameCompare());
        for (Dog a:arrayList){
            System.out.print(a.name+a.age +"\t");
        }
        System.out.println();


        // 判断是否包含
        System.out.println(arrayList.contains(new Dog("aaa ", 11)));


        // hashSet 无序不重复的集合
        HashSet<Dog> hashSet = new HashSet<>(arrayList);
        for (Dog a:hashSet) {
            System.out.print(a.getName()+a.getAge()+"\t");
        }
        System.out.println();


    }
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

电光火石尔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值