我们知道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

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

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

  1. java基础集合经典训练题

    第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...

  2. .Net多线程编程—并发集合

    并发集合 1 为什么使用并发集合? 原因主要有以下几点: System.Collections和System.Collections.Generic名称空间中所提供的经典列表.集合和数组都不是线程安全 ...

  3. 一起学 Java(三) 集合框架、数据结构、泛型

    一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...

  4. 编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议75~78)

    建议75:集合中的元素必须做到compareTo和equals同步 实现了Comparable接口的元素就可以排序,compareTo方法是Comparable接口要求必须实现的,它与equals方法 ...

  5. java基础_集合List与Set接口

    List接口继承了Collection的方法  当然也有自己特有的方法向指定位置添加元素   add(索引,添加的元素); 移除指定索引的元素   remove(索引) 修改指定索引的元素   set ...

  6. Java基础Collection集合

    1.Collection是所有集合的父类,在JDK1.5之后又加入了Iterable超级类(可以不用了解) 2.学习集合从Collection开始,所有集合都继承了他的方法 集合结构如图:

  7. 轻量级“集合”迭代器-Generator

    Generator是PHP 5.5加入的新语言特性.但是,它似乎并没有被很多PHP开发者广泛采用.因此,在我们了解PHP 7对Generator的改进之前,我们先通过一个简单却显而易见的例子来了解下G ...

  8. Asp.net MVC 传递数据 从前台到后台,包括单个对象,多个对象,集合

    今天为大家分享下 Asp.net MVC 将数据从前台传递到后台的几种方式. 环境:VS2013,MVC5.0框架 1.基本数据类型 我们常见有传递 int, string, bool, double ...

  9. 这些.NET开源项目你知道吗?.NET平台开源文档与报表处理组件集合(三)

    在前2篇文章这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧 和这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,大伙热情高涨.再次拿出自己的私货,在.NET平台 ...

  10. python 数据类型 --- 集合

    1. 注意列表和集合的区别 set 列表表现形式: list_1 = [1,3,4];  集合表现形式:set_1= set() list_1 = [1,2,3,4,23,4,2] print(lis ...

随机推荐

  1. FORM - 实现某数据项自动按记录序号加一操作

    ---- 设块名为VO,要操作的数据项为VO_ID,在该块中建立块级触发子WHEN-CREATE- RECORD,每当生成新记录时VO_ID就会自动加一了,加入如下代码: :VO_ID:=:Syste ...

  2. 转载:10个实用的但偏执的Java编程技术

    在沉浸于编码一段时间以后(比如说我已经投入近20年左右的时间在程序上了),你会渐渐对这些东西习以为常.因为,你知道的…… 任何事情有可能出错,没错,的确如此. 这就是为什么我们要采用“防御性编程”,即 ...

  3. USACO3.24Feed Ratios

    直接枚举到100水过 /* ID: shangca2 LANG: C++ TASK: ratios */ #include <iostream> #include<cstdio> ...

  4. JQuery对XML文件的操作

    xml文件如下: <?xml version="1.0" encoding="utf-8" ?> <Root> <Parent&g ...

  5. struts1.3异常处理机制

    当Struts的控制器捕获到异常时,在异常处理块中,创建描述异常信息的ActionMessage对象,并放入ActionMessages对象中.然后把ActionMessages对象存放到一定范围内( ...

  6. 用Oracle的TRIM函数去除字符串首尾指定字符

    去掉首尾空格 SELECT TRIM(' abc '), ltrim(' abc '), rtrim(' abc ') FROM dual; 去掉首尾的其他字符 SELECT /*TRIM(';a;b ...

  7. Unity3d Realtime Dynamic Volume Clouds Rendering

    Ray Marching体积渲染+perlin noise 动态效果: 博主近期渲染: 2016的渲染 2015后半段的渲染 ---- by wolf96

  8. Unity 时间缩放状态下的特效播放

    时间缩放状态下,比如 Time.timeScale 缩小为 0 或者 0.000001 等极小值时,若想将特效的播放速度放大相同的倍数,即修改 ParticleSystem.playbackSpeed ...

  9. 解决 this virtual machine’s policies are too old to be run by this version of vmware workstation”

    VMWare从6.0升级到9.0,打开以前的虚拟机报错如下:“this virtual machine’s policies are too old to be run by this version ...

  10. 使用正则表达式匹配JS函数代码

    使用正则表达式匹配JS函数代码 String someFunction="init"; Pattern regex = Pattern.compile("function ...