我们知道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. 存储过程中“Select Top 变量”的问题如何解决

    在SqlServer2005中,可以这样: DECLARE @p int SELECT TOP (@p) * FROM 表名 在SqlServer2000中,不支持以上方法,可以这样: DECLARE ...

  2. c# post文字图片至服务器

    最近由于项目需要实现c#提交文字及数据至服务器,因此研究了一下c# php数据传送: 下面用一个示例来演示,c# post文字+图片 ,php端接收: post提交数据核心代码(post数据提交) ? ...

  3. NOI2010超级钢琴 2

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 1296  Solved: 606[Submit][Status ...

  4. App Store 加急审核方式

    https://developer.apple.com/contact/app-store/?topic=expedite 1:理由一般是用户安全问题或者崩溃问题成功率会高一些. 如果是崩溃问题,你最 ...

  5. MFC VS2005 添加Override 和 Message

    VS2005 1.Overrides OnInitDialog() 在Class View选中 这个类,然后properties中点Message 旁边的Overrides, 添加OnInitDial ...

  6. (转载)完美解决PHP中文乱码问题

    (转载)http://www.souzz.net/html/edu/php/php1/74181.html 一.首先是PHP网页的编码 1.php文件本身的编码与网页的编码应匹配 a.如果欲使用gb2 ...

  7. HDU4725 The Shortest Path in Nya Graph dij

    分析:对于每一层,原来n个点,然后扩展为原来的三倍,每一层扩展一个入点,一个出点,然后跑最短路 注:tmd我把一个n写成m了,然后wa了7次,我都要怀疑人生了 #include<cstdio&g ...

  8. 如何处理alert、confirm、prompt对话框

    import java.io.File; import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.ope ...

  9. 最近用unity5弄的一些渲染

    unity5 人皮渲染  Skin Shading 换了一种方法,优化了一下代码,unity5效果很好,消耗不大 点开可查看大图 加入了次表面散射的阴影与自阴影 unity5  ocean real- ...

  10. Android 布局优化 -- 学习笔记

    通过一些惯用.有效的布局原则,我们可以制作出加载效率高并且复用性高的UI.简单来说,在Android UI布局过程中,需要遵守的原则包括如下几点: 尽量多使用RelativeLayout,不要使用绝对 ...