您的位置:首页 > 职场人生

黑马程序员 java基础 集合框架之Set

2014-12-01 16:15 405 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

Set集合特点:

set集合中数据的存储和取出是无序的。而且元素时不可以重复;

set集合Collection功能是一样的。list有操作角标的特有方法。但是set集合没有特殊的特性方法。

set集合中常见的子类:

HashSet -----底层的数据结构式哈希表。

TreeSet------底层的数据结构式二叉树。

注:Hash表的特点,先比较对象的hash值,如果hash值不同,然后就根据hash值存储在hash表中,如果hash值相同,那么就会比较对象的equal()方法。如果equal()返回的也是true,那么向hash表中存储元素就会失败。

HashSet集合是如何在保证数据的唯一性的呢?

1主要是通过比较元素本身的hashcode值,

2如果hashcode值相同,那么就在比较元素的equal方法,主要元素的hash值不同,就不会比较equal方法,

如果两个条件中只要有一个不相同,那么元素就会存储成功。

TreeSet实例

/*demo1*/
import java.util.*;
class JavaCollection1_7
{
public static void main(String[] args)
{
HashSet hs=new HashSet();
sop(hs.add("java01"));//第一次添加会添加成功
hs.add("java02");
hs.add("java03");
hs.add("java04");
sop(hs.add("java01"));//当插入重复的元素就会添加失败。
sop(hs);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}


运行结果如下:



实例二:

向HashSet中存自定义的Person类,如果年龄和姓名都相同,就不存储到HashSet中

/*
*/
import java.util.*;
class JavaCollection1_8
{
public static void main(String[] args)
{
HashSet hs=new HashSet();
hs.add(new Person("java01",1));
hs.add(new Person("java02",2));
hs.add(new Person("java03",3));
hs.add(new Person("java01",1));
/*这里向hs集合中添加了重复的人。
*/
for(Iterator it=hs.iterator();it.hasNext();)
{
Person p=(Person)it.next();
sop(p.getName()+":"+p.getAge());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}

}
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
//1元素存储到HashSet中,首先比较的是对象的hashCode()值,
public int hashCode()
{
return name.hashCode()+age;
}
//2如果元素的hashCode值相同,那么就会在比较对象的equsls方法。
public  boolean equals(Object obj)
{
//类型安全转换
if(!(obj instanceof Person))
return false;
Person p=(Person)obj;
return this.name.equals(p.name)&&this.age==p.age;
//如果人的名字和年龄相同,那么人员就重复。
}
}


运行结果如下:



注意:HashSet删除元素,或者是否包含元素,都是先依赖元素的hashcode,然后在依赖元素的equals方法
而ArrayLis集合删除元素,或者是否包含元素,只依赖元素的equals()方法。

TreeSet集合的特点 

可以对set中元素进行排序,而排序的依据主要是根据字符的ASCILL表。

实例一:

import java.util.*;
class JavaCollection1_9
{
public static void main(String[] args)
{
TreeSet ts=new TreeSet();
ts.add("abcde");
ts.add("bcd");
ts.add("c");
ts.add("adc");
for(Iterator it=ts.iterator();it.hasNext();)
{
System.out.println(it.next());
}
}
}
运行结果如下:



很明显,我们存储的顺序是无序的,但是输出的结果却是按照字符的ASCILL表的顺序输出的,说明TreeSet有对元素进行排序的功能。

下面我们向集合中存储自定义的对象。

注意:向TreeSet中存储的自定义对象必须具有比较性。不然程序编译就会报异常。所以自定义的对象必须实现Comparable接口,并覆盖里面的compareTo()方法。

另外在排序时,先要对主要条件进行排序,然后再对次要条件进行排序。

实例二:

需求:向TreeSet中存储多个学生,按照学生的年龄的大小排序。

/**/
import java.util.*;
class JavaCollection1_10
{
public static void main(String[] args)
{
TreeSet ts=new TreeSet();
ts.add(new Person("xt",21));
ts.add(new Person("tx",21));
ts.add(new Person("xt",22));
ts.add(new Person("xt",21));
for(Iterator it=ts.iterator();it.hasNext();)
{
Person p=(Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
}
class Person implements Comparable/*存储到TreeSet中的自定义对象必须具备比较性,所以这里强制学生实Comparable接口,并实现compareTo()方法*/
{
private int age;
private String name;
public int compareTo(Object obj)
{
if(!(obj instanceof Person))
throw new ClassCastException("TreeSet中存储了非Person类型的对象");
Person p=(Person)obj;
if(this.age>p.getAge())
return 1;
if(this.age==p.getAge())//注意:这里当主条件相同时,我们还要比较次要条件,如果不比较名称,那么当年龄相同时,往TreeSet中存储时就可能存储失败。
{
//先比较年龄;再比较姓名;
return this.name.compareTo(p.getName());
}
return -1;
}
Person(String name,int age)
{
this.age=age;
this.name=name;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}


运行结果如下:



实例三:

TreeSet集合底层的数据结构是二叉树,而且下来的实例将显示数据在TreeSet中的存储方式,代码如下:

总结:TreeSet实例排序的第一种方式,让元素本身具备比较性,实现Comparable接口,并重写compareTo方法。

import java.util.*;
class JavaCollection1_11
{
public static void main(String[] args)
{
TreeSet ts =new TreeSet();
ts.add(45);
ts.add(76);
ts.add(34);
ts.add(89);
ts.add(23);
ts.add(40);
ts.add(12);
ts.add(4);
for(Iterator it=ts.iterator();it.hasNext();)
{
System.out.println(it.next());
}
}
}



数据在TreeSet的存储结构就如上面的截图二叉树结构,TreeSet取出的方式是默认方式,按照从小到大的方式,

运行结果:



TreeSet的第二种排序方式:当元素本身不具备比较性,或者是元素本身的比较性不是自己所需的,那么我们就需要集合具备比较性,在集合初始化就具备比较性;这时我们就需要定义一个比较器,然后将比较器对象作为参数传递给集合的构造函数。让集合具备比较性;

实例三:

创建TreeSet集合,集合中存储Person对象,并进行排序,首先按照人名排序,如果人名相同,再按照年龄进行排序,代码如下:

import java.util.*;
class
4000
JavaCollection1_12
{
public static void main(String[] args)
{
//将比较器对象作为参数传递给集合的构造函数,让集合具备比较性。
TreeSet ts=new TreeSet(new MyComparator());
ts.add(new Person("xt",21));
ts.add(new Person("tx",22));
ts.add(new Person("aa",34));
ts.add(new Person("aa",22));
for(Iterator it=ts.iterator();it.hasNext();)
{
Person p=(Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
}

//创建一个比较器:
class MyComparator implements Comparator//比较器必须要是实现Comparator接口
{
//重写Comparator接口中的compare方法。
public int compare(Object obj1,Object obj2)
{
if(obj1 instanceof Person&&obj2 instanceof Person)
{
Person p1=(Person)obj1;
Person p2=(Person)obj2;
int num=p1.getName().compareTo(p2.getName());
if(num==0)//当名字相同时就应该比较年龄。
return p1.getAge()-p2.getAge();
else
return num;
}
else
{
throw new ClassCastException("集合中存储的对象不是Person类型的");
}
}
}
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
运行结果如下:



注意事项:

当元素自身具备比较性,同时TreeSet集合也具备比较性,那么比较的依据是依赖集合的比较性。也就是比较器的比较方式。

TreeSet练习:

需求:往TreeSet中存入几个字符串,然后按照先参照字符串的长度排序,长度相同,然后在按照字符串的ASCILL码表的顺序进行排序,代码如下:

import java.util.*;
class JavaCollection1_14
{
public static void main(String[] args)
{
//使用匿名内部类来创建比较器;
TreeSet ts=new TreeSet(new Comparator(){
public int compare(Object obj1,Object obj2)
{
if(!(obj1 instanceof String )||!(obj2 instanceof String))
throw new ClassCastException("存入到TreeSet中的元素不是String类型的");
String str1=(String)obj1;
String str2=(String)obj2;
int num=str1.length()-(str2.length());
if(num==0)
return str1.compareTo(str2);
return num;
}

});
ts.add("c");
ts.add("aaa");
ts.add("b");
ts.add("bca");
System.out.println(ts);
}
}
运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: