集合练习——Set部分

我们知道list存储的是有序不唯一的元素。

set存储的是无序唯一的元素。

那么下面看一个例子吧:

package CollectionPart;

import java.util.HashSet;
import java.util.Set;

public class HashSet1 {
    public static void main(String[] args) {
        Set mySet = new HashSet();
        mySet.add("df");
        mySet.add("df");
        System.out.println(mySet.size());
        for (Object object : mySet) {
            System.out.println(object);
        }
    }
}

运行结果:

1
df

这就充分说明了,set集合里面存储的元素是唯一的。

那么如下代码将会反映一个问题:

package CollectionPart;

import java.util.HashSet;
import java.util.Set;

public class HashSet1 {
    public static void main(String[] args) {
        Set mySet = new HashSet();
        mySet.add("df");
        mySet.add("df");

        Employee_1 e1 = new Employee_1("1","lifei",23,"2013-02-09");
        Employee_1 e2 = new Employee_1("1","lifei",23,"2013-02-09");

        mySet.add(e1);
        mySet.add(e2);

        System.out.println(mySet.size());
        for (Object object : mySet) {
            System.out.println(object);
        }
    }
}

运行结果:

3
df
Employee_1 [employeeId=1, employeeName=lifei, employeeAge=23, employeeHireDate=2013-02-09]
Employee_1 [employeeId=1, employeeName=lifei, employeeAge=23, employeeHireDate=2013-02-09]

我们存储的元素明明一模一样,但是结果好像不如人意,不是说好set里面存储的都是不同的元素么,e1 跟e2明显是 同一个对象。

这就需要考量set集合在判定元素是否相等的时候,是通过什么进行判别的。

鼠标移到这个 add方法上面就会有提示:

Adds the specified element to this set if it is not already present. More formally, adds the specified element e to this set if this set contains no element e2 such that (e==null ? e2==null : e.equals(e2)). If this set already contains the element, the call leaves the set unchanged and returns false.

这个说明还是有必要读一下的:添加特定元素给set集合,如果不存在这样一个元素的时候。通常情况下,为当前set集合添加元素e时,如果这个set集合没有已经存在一个e2的话,【通过equals函数来比较】如果已经存在此元素的话,那么add方法的调用并不会修改set集合,并且会返回false。

//有两个点要试:1、null的值可以存储几个,从说明上感觉是1个。2、第二次添加已经存在的元素的时候,会报添加失败,而不是第二次的值覆盖第一次的值。这个是纯想象的,因为覆盖就有添加了一次,这感觉上会产生更多的操作。不如不允许添加来的效率高。

package CollectionPart;

import java.util.HashSet;
import java.util.Set;

public class HashSet1 {
    public static void main(String[] args) {
        Set mySet = new HashSet();
        mySet.add("df");
        boolean add = mySet.add("df");

        System.out.println("是否添加成功:"+add);
        Employee_1 e1 = new Employee_1("1","lifei",23,"2013-02-09");
        Employee_1 e2 = new Employee_1("1","lifei",23,"2013-02-09");

        mySet.add(e1);
        mySet.add(e2);

        System.out.println(mySet.size());
        for (Object object : mySet) {
            System.out.println(object);
        }
        mySet.add(null);
        boolean add2 = mySet.add(null);
        System.out.println("是否添加成功:"+add2+",此时set集合中的元素个数:"+mySet.size());
    }
}

运行结果:

是否添加成功:false
3
df
Employee_1 [employeeId=1, employeeName=lifei, employeeAge=23, employeeHireDate=2013-02-09]
Employee_1 [employeeId=1, employeeName=lifei, employeeAge=23, employeeHireDate=2013-02-09]
是否添加成功:false,此时set集合中的元素个数:4

接下来就要处理,这个 equals的问题了,就可以回去考究这个 set集合中对于元素的equals的方法的比较了,毕竟,e1 跟e2 是一个人。要想办法,把它们区分开。查看默认的 Employee中的equals方法

我们所写的员工类里面并没有一个 equals方法,说明这是 继承来的:所以敲出equals 坐等联想然后得到这样一个函数:

@Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        return super.equals(obj);
    }

鼠标放在 equals上面得到这样一个说明:

Indicates whether some other object is "equal to" this one.

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

简单翻译一下:欢迎斧正,

判断其他的对象是否与当前对象相等。

反射性?reflexive?:对于任何值,x.equals(s) 应该返回true.

对称性:对于非空值x,y,如果x.equals(y)返回true时,当且仅当y.equals(x)也返回true.

传递性:对于非空值x,y和z,如果 x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)应该也返回true.

一致性?:不论怎么调用,结果都应该是一致的,要么true,要么false,当参与比较的两个非空值,x,y,在这种不断地比较过程中始终未被修改的时候。

对于非空值 x,x.equals(null) 的返回值应该是false.

equals方法用来描述object类中两个对象是否相等的关系,如果非空值x,y的返回结果是true的话,那么x,y执行的是相同的实体。

注:通常情况下也要重写hashCode方法,只要equals方法被重写。为了hashCode方法保持总体联系,为了标明相同的对象具有相同的hash码。

所以,这才是 Set集合要注意的地方,只要使用Set集合的话,就要记得重写equals 方法和 hashCode方法。【好在这两个方法都可以自动生成。】

在ssh里面,如果用到多对多的情况的时候,要记得重写这两个方法。

不过重点好像还是没有解释清楚。就是 e1 究竟为什么不等于e2.

我们通过快捷键ctrl+鼠标左键,找到他的实现方法:

public boolean equals(Object obj) {
        return (this == obj);
    }

发现。他们在底层调用的就是这样的语句,那么问题来了,这比较的是什么,this指代的是什么?我们通常在校验是否空指针的时候总会,输出一下,当前对象。那么这个比较就是返回的当前这个 对象的地址值,如果 这个 值不相等的话,就认为两者不相等。好了,那么现在我们认为 id相同并且,姓名相同的话,这两个元素就是一个实体,事实上,最好把所有属性都包含进去,但是 可以利用后期系统的某些存在唯一性约束的属性,作为两个实体是否相等的标识。

Set集合要说明的就是这一个一定要重写 equals() 方法和 hashCode()方法,别的没有了。

习题:打印员工姓名及性别,利用迭代器遍历

员工的字段有 工号 姓名 年龄 入职时间。

由于改写了 员工类的 不妨新写一个 实体类。

//写的时候 复制的,所以 就输出 姓名和年龄吧

package CollectionPart;

/**
 * 为了Set的联系,比Employee_1多重写了两个方法
 *
 */
public class Employee_2 {

    private String employeeId;
    private String employeeName;
    private int employeeAge;
    private String employeeHireDate;
    /*
    这里就存储成String 类型,在 数据库里面设置成 date格式。
    然后 利用Date today = new Date();
    SimpleDateFormat fm = new SimpleDateFormat("YYYY-MM-dd");
    来做
    */
    public String getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(String employeeId) {
        this.employeeId = employeeId;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public int getEmployeeAge() {
        return employeeAge;
    }
    public void setEmployeeAge(int employeeAge) {
        this.employeeAge = employeeAge;
    }
    public String getEmployeeHireDate() {
        return employeeHireDate;
    }
    public void setEmployeeHireDate(String employeeHireDate) {
        this.employeeHireDate = employeeHireDate;
    }
    @Override
    public String toString() {
        return "Employee_1 [employeeId=" + employeeId + ", employeeName=" + employeeName + ", employeeAge="
                + employeeAge + ", employeeHireDate=" + employeeHireDate + "]";
    }
    public Employee_2(String employeeId, String employeeName, int employeeAge, String employeeHireDate) {
        super();
        this.employeeId = employeeId;
        this.employeeName = employeeName;
        this.employeeAge = employeeAge;
        this.employeeHireDate = employeeHireDate;
    }
    public Employee_2() {
        super();
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + employeeAge;
        result = prime * result + ((employeeHireDate == null) ? 0 : employeeHireDate.hashCode());
        result = prime * result + ((employeeId == null) ? 0 : employeeId.hashCode());
        result = prime * result + ((employeeName == null) ? 0 : employeeName.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee_2 other = (Employee_2) obj;
        if (employeeAge != other.employeeAge)
            return false;
        if (employeeHireDate == null) {
            if (other.employeeHireDate != null)
                return false;
        } else if (!employeeHireDate.equals(other.employeeHireDate))
            return false;
        if (employeeId == null) {
            if (other.employeeId != null)
                return false;
        } else if (!employeeId.equals(other.employeeId))
            return false;
        if (employeeName == null) {
            if (other.employeeName != null)
                return false;
        } else if (!employeeName.equals(other.employeeName))
            return false;
        return true;
    }}
package CollectionPart;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetPractise_1 {
    public static void main(String[] args) {
        Employee_2 e1= new Employee_2("dept1_001", "lifei", 23, "2016-02-05");
        Employee_2 e2= new Employee_2("dept1_001", "lifei", 23, "2016-02-05");
        Employee_2 e3= new Employee_2("dept1_002", "life2", 24, "2016-03-05");
        Employee_2 e4= new Employee_2("dept3_001", "life3", 28, "2015-03-05");
        Set<Employee_2> mySet = new HashSet<Employee_2>();
        mySet.add(e1);
        mySet.add(e2);
        mySet.add(e3);
        mySet.add(e4);
        Iterator<Employee_2> iterator = mySet.iterator();
        System.out.println("员工人数为:"+mySet.size());
        while (iterator.hasNext()) {
            Employee_2 employee_2 = iterator.next();
            System.out.println("当前员工: "+employee_2.getEmployeeName()+" ,年龄为:"+employee_2.getEmployeeAge());
        }
    }
}

运行结果:

员工人数为:3
当前员工: life3 ,年龄为:28
当前员工: lifei ,年龄为:23
当前员工: life2 ,年龄为:24

发现一个事儿,就是 确实是无序的。

时间: 2024-10-10 17:14:30

集合练习——Set部分的相关文章

数组、字符串、集合

数组与集合的转换.数组与字符串的转换 ========数组变集合 String[] arr = {"abc","cc","kkkk"}; //把数组变成list集合有什么好处? /* 可以使用集合的思想和方法来操作数组中的元素. 注意:将数组变成集合,不可以使用集合的增删方法. 因为数组的长度是固定. contains. get indexOf() subList(); 如果你增删.那么会产生UnsupportedOperationExcepti

C#语言中数组和集合

数组.集合→用于储存多个同类型的数据数组 定长→用于保存固定数量的数据 在功能上,数组能实现的所有功能,集合都能实现:反之,集合能实现的某些功能,数组难以实现 占用内存少 便利速度快集合 不定长→保存的数据数量,可以在程序的执行过程中,发生变化 占用内存多 便利速度慢课时六:数组和集合 数组.集合→用于储存多个同类型的数据 数组 定长→用于保存固定数量的数据 在功能上,数组能实现的所有功能,集合都能实现:反之,集合能实现的某些功能,数组难以实现 占用内存少 便利速度快 集合 不定长→保存的数据数

通过反射了解集合泛型的本质

通过反射了解集合泛型的本质 import java.lang.reflect.Method; import java.util.ArrayList; /** * 通过反射了解集合泛型的本质 * @author shm * */ public class MethodDemo02 { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("hello"); list.add(

Java 之集合

collection(单列集合) List(有序,可重复) ArrayList     底层数据结构是数组,查询快,增删慢,线程不安全,效率高 Vector     底层数据结构是数组,查询快,增删慢,线程安全,效率低 LinkedList  底层数据结构是链表,查询慢,增删快,线程不安全,效率高 Set(无序,唯一) HashSet   底层数据结构是哈希表,依赖hashCode()和equals() 执行顺序:判断hashCode()是否相同,相同继续执行equals(),返回true不添加

集合和三元运算符

一.三元运算符 如下判断可以使用三元运算更方便的实现: a = 1b = 2 if a > 1: c = aelse: c = b 和下面是一样的: a = 1b = 2#下面这个c = a if a>1 else b 如下两种方法也是一样的:方式一: s=[]nums = list(range(1,11))for i in nums: if i%2==0: s.append(i)print(s)方式二:ss = [i for i in nums if i%2==0]print(ss)#这两种

集合函数 day4

1.集合 通过set强制转换,或者直接定义 1 nums = [0, 2, 4, 6, 8]#两种格式,带大括号与带中括号的 2 print(type(nums)) 3 aa = {0, 8, 2, 4, 6}#需要注意与字典的区别,字典是有分号的 2.交集

js算法集合(一) 水仙花数 及拓展(自幂数的判断)

js算法集合(一) ★ 最近有些朋友跟我说对js中的一些算法感到很迷惑,知道这个算法到底是怎么回事,但是就是不会用代码把它写出来,这里我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,希望能对大家有所帮助. 1.验证一个数是否为水仙花数 ①要写水仙花数的算法,我们首先来了解一下什么是水仙花数,水仙花数是指一个 3位正整数 ,它的每个位上的数字的 3次幂之和等于它本身.(例如:1^3 + 5^3+ 3^3 = 153): ②了解了什么是水仙花数我们就开始分析该怎么下手.通过定义来看

笔记:多线程-集合

阻塞队列(BlockingQueue) 当试图向队列添加元素而队列已满,或是想从队列移除元素而队列为空的时候,阻塞队列导致线程阻塞,阻塞队列接口定义如下,他继承Queue<E>接口: public interface BlockingQueue<E> extends Queue<E> { ????/** ???? * 添加一个元素,如果队列满,则抛出 IllegalStateException异常 ???? */ ????????boolean add(E e); ??

SQL入门之集合操作

尽管可以在与数据库交互时一次只处理一行数据,但实际上关系数据库通常处理的都是数据的集合.在数学上常用的集合操作为:并(union),交(intersect),差(except).对于集合运算必须满足下面两个要求: 两个数据集合必须具有同样数目的列 连个数据集中对应列的数据类型必须是一样的(或者服务器能够将其中一种类型转换为另一种类型) SQL语言中每个集合操作符包含两种修饰:一个包含重复项,另一个去除了重复项(但不一定去除了所有重复项). 0.union操作符 union和union all操作

Java—集合框架List

集合的概念 现实生活中:很多的事物凑在一起 数学中的集合:具有共同属性的事物的总和 Java中的集合类:是一种工具类,就像是容器,存储任意数量的具有共同属性的对象 集合的作用 在类的内部,对数据进行组织(针对作用与意义一样的属性,将他们放到一个集合中) 简单而快速的搜索大数量的条目 有的集合接口,提供了一系列排列有序的元素,并且可以在序列中快速的插入或删除有关元素 有的集合接口,提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型 与数组相比 数组的长度