集合框架 Set的特点:无序,不可以重复元素。

(1)HashSet:数据结构是哈希表。线程是非同步的。

              保证元素唯一性的原理:判断元素的hashCode值是否相同。

              如果相同,还会继续判断元素的equals方法,是否为true。





(2)TreeSet:可以对Set集合中的元素进行排序。

               底层数据结构是二叉树。

               保证元素唯一性的依据:compareTo方法return 0。



一、HashSet相关知识

    HashSet中的元素不可以重复,如果重复添加,则只会显示一个。

原理如下:

HashSet:底层数据结构是哈希表。是线程不安全的。不同步。

HashSet是如何保证元素唯一性的呢?

答:是通过元素的两个方法,hashCode和equals来完成。

如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。



*******对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法**********



代码1:

package com.package2;

import java.util.*;

public class HashSet222
{ public static void main(String[] args)
{ HashSet hs = new HashSet(); hs.add("java01");
hs.add("java01");
hs.add("java02");
hs.add("java03");
hs.add("java03");
hs.add("java04"); Iterator it = hs.iterator(); while(it.hasNext())
{
System.out.println(it.next());
}
}
}

此demo将String类型的字符串添加进去,并且没有重复,结果如下:

java04

java02

java03

java01

由此我们可以断定,String类已经实现了hashcode()方法和equals()方法。打开,帮助文档,确实(这不是废话么^_^)

但是,如果我们要将自定义的元素add进HashSet中,则必须定义其自己的hashcode()方法和equals()方法。如下所示:

代码2:

package com.package2;
import java.util.*;
public class HashSet3
{
public static void main(String[] args)
{
HashSet hs = new HashSet(); hs.add(new Person("a1",11));
hs.add(new Person("a2",12));
hs.add(new Person("a3",13));
hs.add(new Person("a2",12));
hs.add(new Person("a4",14)); Iterator it = hs.iterator(); while(it.hasNext())
{
Person p = (Person)it.next();
System.out.println(p.getName()+"::"+p.getAge());
}
}
}
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
} public int hashCode()
{
System.out.println(this.name+"....hashCode");
return name.hashCode()+age*37; //保证此元素的返回值尽量不一致。
} public boolean equals(Object obj)
{ if(!(obj instanceof Person))
return false; Person p = (Person)obj;
System.out.println(this.name+"...equals.."+p.name); return this.name.equals(p.name) && this.age == p.age;
} public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}

输出结果如下:

a1....hashCode

a2....hashCode

a3....hashCode

a2....hashCode

a2...equals..a2

a4....hashCode

a1::11

a3::13

a2::12

a4::14

由此可以看出,将元素add时,会首先调用元素的hashcode()方法,当返回值重复时,会调用其equals方法。缺少任何一种方法都构不成一个HashSet集合。





二、TreeSet相关知识

TreeSet有俩种排序方式。

TreeSet排序的第一种方式:让元素自身具备比较性。

步骤:将add进TreeSet中的元素实现Comparable接口,并且覆盖compareTo方法。这种顺序也是元素的自然顺序,或者叫做默认顺序。



TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性(即利用其另一种构造函数建立对象)。在集合初始化时,就有了比较方式。

步骤:利用某个指定类实现Comparator接口,并且覆盖compare()方法,则此类会成为一个具备比较方法的类。在建立TreeSet的时候,将此类对象传入其中。

则此时,添加进TreeSet中的元素可按照指定比较方法进行排序。



下边举例演示俩种排序方式。

排序方式一:代码1:

package com.package1;

import java.util.*;

public class TreeSettest {

	public static void main(String[] args) {
//创建对象
TreeSet ts=new TreeSet(); //添加元素
ts.add("abcjjj");
ts.add("abb");
ts.add("daccc");
ts.add("gfg");
ts.add("geee");
ts.add("r"); //进行迭代
Iterator it=ts.iterator(); //循环取出元素
while(it.hasNext())
{
System.out.println(it.next());
} } }

输出结果如下:

abb

abcjjj

daccc

geee

gfg

r

由此可见,此时元素具备可比性,即按照其自然顺序进行排序。打开帮助文档,我们可以清晰的发现String已经实现了Comparable接口,并且已经覆盖了compareTo(),“这不是废话么^_^”,如图所示:







ps……如果我们要往TreeSet里添加的元素是自己刚刚定义的,我们也可以自己定义该元素的类实现Comparator接口,并且覆盖compareTo()方法,如下所示:代码2:

package com.package1;

import java.util.*;

class Student implements Comparable//该接口强制让学生具备比较性。
{
private String name;
private int age; Student(String name,int age)
{
this.name = name;
this.age = age;
} public int compareTo(Object obj)
{ //return 0; if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student)obj; //System.out.println(this.name+"....compareto....."+s.name);
if(this.age>s.age)
return 1;
if(this.age==s.age)
{
return this.name.compareTo(s.name);
}
return -1;
/**/
} public String getName()
{
return name; }
public int getAge()
{
return age;
}
}
public class TreeSet2
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(); ts.add(new Student("lisi02",22));
ts.add(new Student("lisi02",21));
ts.add(new Student("lisi007",20));
ts.add(new Student("lisi09",19));
ts.add(new Student("lisi06",18));
ts.add(new Student("lisi06",18));
ts.add(new Student("lisi007",29));
//ts.add(new Student("lisi007",20));
//ts.add(new Student("lisi01",40)); Iterator it = ts.iterator();
while(it.hasNext())
{
Student stu = (Student)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}

结果如下:

lisi06...18

lisi09...19

lisi007...20

lisi02...21

lisi02...22

lisi007...29

此例子将学生元素,强行按照年龄来排序,这就是我们想要的排序方式。



第二种排序如下:

还是刚刚代码1的例子,我们使用第二种排序方式,使得String类型的元素按照长度来排序。

代码3:

/*
* 使元素按照长度来排序,若长度相同,则按照自然排序。
*/
public class TreeSettest { public static void main(String[] args) {
//创建对象
TreeSet ts=new TreeSet(new MyCompare()); //添加元素
ts.add("abc");
ts.add("bcc");
ts.add("das");
ts.add("bcde");
ts.add("asdfg");
ts.add("befqfca"); //进行迭代
Iterator it=ts.iterator(); //循环取出元素
while(it.hasNext())
{
System.out.println(it.next());
} } } //定义一个类实现Comparator接口,并且覆盖compare()方法。
class MyCompare implements Comparator
{ @Override
public int compare(Object o1, Object o2) {
//进行强制类型转换
String s1=(String) o1;
String s2=(String) o2; //进行比较
if(s1.length()>s2.length())
return 1;
if(s1.length()<s2.length())
return -1;
if(s1.length()==s2.length())
{
return s1.compareTo(s2);
}
return 0;
}
}

结果如下:

abc

bcc

das

bcde

asdfg

befqfca

此种情况下,我们不方便修改源代码,而只需要修改比较方法时,我们就可以自己创建一个比较器。在建立TreeSet时,将比较器传入即可使元素按照特定比较方式输出。

总结:

Comparable(方式一)接口和Compartor(方式二)接口的比较:

两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但

是需要修改源代码。

用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把

比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其

可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

















Java集合框架—Set的更多相关文章

  1. Java集合框架List,Map,Set等全面介绍

    Java集合框架的基本接口/类层次结构: java.util.Collection [I]+--java.util.List [I]   +--java.util.ArrayList [C]   +- ...

  2. Java集合框架练习-计算表达式的值

    最近在看<算法>这本书,正好看到一个计算表达式的问题,于是就打算写一下,也正好熟悉一下Java集合框架的使用,大致测试了一下,没啥问题. import java.util.*; /* * ...

  3. 【集合框架】Java集合框架综述

    一.前言 现笔者打算做关于Java集合框架的教程,具体是打算分析Java源码,因为平时在写程序的过程中用Java集合特别频繁,但是对于里面一些具体的原理还没有进行很好的梳理,所以拟从源码的角度去熟悉梳 ...

  4. Java 集合框架

    Java集合框架大致可以分为五个部分:List列表,Set集合.Map映射.迭代器.工具类 List 接口通常表示一个列表(数组.队列.链表 栈),其中的元素 可以重复 的是:ArrayList 和L ...

  5. Java集合框架之map

    Java集合框架之map. Map的主要实现类有HashMap,LinkedHashMap,TreeMap,等等.具体可参阅API文档. 其中HashMap是无序排序. LinkedHashMap是自 ...

  6. 22章、Java集合框架习题

    1.描述Java集合框架.列出接口.便利抽象类和具体类. Java集合框架支持2种容器:(1) 集合(Collection),存储元素集合 (2)图(Map),存储键值对.

  7. Java集合框架实现自定义排序

    Java集合框架针对不同的数据结构提供了多种排序的方法,虽然很多时候我们可以自己实现排序,比如数组等,但是灵活的使用JDK提供的排序方法,可以提高开发效率,而且通常JDK的实现要比自己造的轮子性能更优 ...

  8. (转)Java集合框架:HashMap

    来源:朱小厮 链接:http://blog.csdn.net/u013256816/article/details/50912762 Java集合框架概述 Java集合框架无论是在工作.学习.面试中都 ...

  9. Java集合框架

    集合框架体系如图所示 Java 集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包. Map接口的常用方法 Map接口提 ...

  10. Java集合框架(常用类) JCF

    Java集合框架(常用类) JCF 为了实现某一目的或功能而预先设计好一系列封装好的具有继承关系或实现关系类的接口: 集合的由来: 特点:元素类型可以不同,集合长度可变,空间不固定: 管理集合类和接口 ...

随机推荐

  1. 虚拟机 Linux

    VBox ubuntu安装增强功能

  2. python2 + selenium + eclipse 中,通过django生产数据库表的时候报错

    python2 + selenium + eclipse 中,通过django生产数据库表的时候报错 解决: 1.查看自己电脑中,“开始-->控制面板-->管理工具-->服务--&g ...

  3. QT时钟绘制

    Demo的效果 资源占用还能接受 运行久一点内存就下去了 下面是Demo的代码 #include "mainwindow.h" #include "ui_mainwind ...

  4. thinkpad取消fn键功能

    转自:https://bbs.thinkpad.com/thread-1834235-1-1.html 1就是一直觉得fn建自动开启很烦人,于是百度后得到 我们可以 控制面板 -- 键盘--think ...

  5. Acdream手速赛7

    蛋疼啊,本次只做出了一道题目...渣爆了... 妈蛋,,卡题之夜..比赛结果是1道题,比赛完哗啦哗啦出4道题.. A acdream1191 Dragon Maze 题意: 给一个迷宫,给出入口坐标和 ...

  6. linux中syslog自定义存储路径的方法

    方法一: 1. su  //切换到root用户下2. cp /etc/sysconfig/rsyslog /etc/sysconfig/rsyslogbak //备份vim /etc/sysconfi ...

  7. VC OnCtlColor函数来修改控件背景颜色

    CWnd::OnCtlColor afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor ); 返回值:OnCtlColor必须 ...

  8. 洛谷P3379 【模板】最近公共祖先(LCA)(dfs序+倍增)

    P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询 ...

  9. 从扫码支付想到的超级APP主宰一切,数据!数据!还是数据!

    前言 做室内定位的人其实内心都明白:基于指纹方法的移动端定位,无论paper每年出来多少,距离真正的大规模应用的距离还有多么遥远.指纹采集,指纹更新,似乎在生产实践上就是不可能的难题.所有还在基于人工 ...

  10. Cinder服务使用

    Cinder环境 Cinder配置 重新创建卷组cinder-volumes [root@openstack centos]# vgremove cinder-volumes Configuratio ...