java集合之set

java集合大致上可分为:set,list,map三种体系,其中set代表无序不可重复的集合,list代表有序可重复的集合,map代表具有映射关系的集合。后来又增加一种Queue体系集合,代表一种队列的集合实现。set和list接口都实现了collection接口

使用Iterator接口遍历集合元素
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class TestIterator {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建一个集合
Collection books = new HashSet();
books.add("book1");
books.add("book2");
books.add("book3");
books.add("book4");
//获取Iterator迭代器
Iterator it = books.iterator();
while(it.hasNext()){
//it.next()方法返回的数据类型是Object类型,需要强制类型转换
String book = (String)it.next();
System.out.println(book);
if(book.equals("book3")){
//从集合中删除上一次next返回的元素
it.remove();
//使用Iterator迭代器过程中,不可修改集合元素,所以下面代码引发异常
//books.remove("book3");
}
//对book变量赋值,不会改变元素本身
book= "book9";
}
System.out.println(books);
}

}

Iterator必须依附于Collection对象。有一个Iterator对象,则必然有一个与之关联的的Collection对象。

使用foreach遍历集合元素更加简洁
import java.util.Collection;
import java.util.HashSet;

public class TestIterator {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建一个集合
Collection books = new HashSet();
books.add("book1");
books.add("book2");
books.add("book3");
books.add("book4");
for(Object obj : books)
{
String book = (String)obj;
System.out.println(book);
if(book.equals("book3")){

//使用循环过程中,不可修改集合元素,所以下面代码引发异常
//books.remove("book3");
}
}

System.out.println(books);
}

}

Set接口

实际上Set就是Collection,只是Set不允许包含重复元素

Set通过equals方法判断两个对象是否相同,而不是==,所以只要equals返回true,那么两个对象就是相同的,无论实际上这两个对象差别有多大,而只要equals返回false,即使两个对象实际上是同一个对象,Set也会当成两个对象处理。
例如:
import java.util.HashSet;
import java.util.Set;

public class TestSet {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Set books = new HashSet();
books.add("book1");
boolean result = books.add(new String("book1"));
System.out.println(result);
System.out.println(books);
}

}
将输出false book1

HashSet,TreeSet,EnumSet三个类实现了Set接口


HashSet类
HashSet具有的特点:
1 不能保证元素的排列顺序,顺序可能发生变化。
2 HashSet不是同步的,如果多个线程同时访问一个Set集合,如果多个线程同时访问一个HashSet,如果有2条或者以上的线程修改了 HashSet集合时,必须通过代码来保证其是同步的(TreeSet和EnumSet也一样)。
3 集合元素可以是null。

HashSet判断两个元素相等是的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode方法返回的值也相等。
如果equals比较相等,hashCode返回值不同,则HashSet将会把两个对象保存到不同的位置,即都添加成功
如果equals不相等,hashCode返回值相等,则HashSet将会试图把两个对象保存到同一个位置,实际上又不行,处理起来将很复杂,将导致性能下降。

所以,重写某个类的equals方法和hashCode方法时,应该尽量保证对象通过equals返回true是,它们的hashCode返回值也相等。

重写hashCode的基本规则
1 过equals返回true是,它们的hashCode返回值也相等
2 对象中用作equals比较标准的属性,都应该用来计算hashCode值。

当向HashSet中添加可变对象是,必须非常的小心,如果修改HashSet中的对象时,有可能导致该对象与集合中的其他对象相等,从而导致HashSet无法准确访问该对象。

HashSet的子对象LinkedHashSet使用链表维护元素次序,使元素以插入顺序保存,性能略低于HashSet。


TreeSet类
TreeSet是SortedSet接口的唯一实现,可以确保元素处于排序状态
TreeSet通用方法示例:
import java.util.TreeSet;

public class TestTreeSet {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet nums = new TreeSet();
//向TreeSet添加4个Integer对象
nums.add(5);
nums.add(2);
nums.add(10);
nums.add(-9);
//输出集合元素
System.out.println(nums);
//输出集合里的第一个元素
System.out.println(nums.first());
//输出集合里的最后一个元素
System.out.println(nums.last());
//返回小于4的子集、不包含4
System.out.println(nums.headSet(4));
//返回大于5的子集、包含5
System.out.println(nums.tailSet(5));
//返回大于-3,小于4的子集
System.out.println(nums.subSet(-3, 4));
}

}


与HashSet集合采用hash算法来决定元素的存储位置不同,TreeSet集合采用红黑树的数据结构来对元素进行排序,分自然排序和定制排序俩种,默认的情况下采用自然排序。

试图把一个对象添加到TreeSet时,该对象的类必须实现Comparable接口,否则出现异常(添加第一个时没事,添加第二个时,TreeSet调用该对象的CompareTo(Object obj)方法时引发异常),而且向TreeSet添加的对象应该属于同一个类的对象,否则也会引发异常。

一些常用类已经实现了Comparable接口,比如BigDecimal,BigInteger,Character,Boolean(true>false),String,Date,Time等
对于TreeSet而言,判断两个对象不相等的标准是:equals方法返回false,或compareTO方法没有返回0,即使两个对象是同一个对象也会当做两个对象处理。所有当重写一个须放入TreeSet的类的equals方法时,应该保证与compareTo方法有一致的结果。

如果向TreeSet中添加一个可变对象后,并且后面的程序修改了该对象的属性,导致它与其他对象的大小发生了变化,但TreeSet不会再次调整它们的顺序,甚至导致保存的这两个对象通过equals返回true,而compareTo确返回0,所有推荐HashSet和TreeSet集合中只放入不可变对象。

示例:
import java.util.TreeSet;

class R implements Comparable{
int count;
public R(int count){
this.count = count;
}
public String toString(){
return "R(count属性:"+count+")";
}
public boolean equals(Object obj){
if(obj instanceof R){
R r = (R)obj;
if(r.count == this.count){
return true;
}
}
return true;
}
public int compareTo(Object obj){
R r = (R)obj;
if(this.count > r.count)
{
return 1;
}
else if(this.count == r.count){
return 0;
}
else {
return -1;
}
}
}

public class TestTreeSet2 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet ts = new TreeSet();
ts.add(new R(5));
ts.add(new R(-3));
ts.add(new R(9));
ts.add(new R(-2));
System.out.println(ts);
// 取出第一个元素
R frist = (R)ts.first();
//改变其属性值
frist.count = 20;
//取出最后一个元素
R last = (R)ts.last();
//改变其属性值
last.count = -2;
System.out.println(ts);
//删除已更改的元素失败
ts.remove(new R(-2));
System.out.println(ts);
//删除未更改的元素成功
ts.remove(new R(5));
System.out.println(ts);
}

}

EnumSet
EnumSet是一个专门为枚举类设计的集合,内部以向量的方式存储,占用内存很少,运行效率很高
EnumSet不允许加入null元素,否则会出现异常
当试图复制一个Collection集合里的元素来创建EnumSet集合时,必须保证Collection集合里的所有元素都是同一个枚举类的枚举值。
示例:
import java.util.EnumSet;

enum Season{
SPRING,SUMMER,FALL,WINTER;
}

public class EnumSetDemo {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
EnumSet es1 = EnumSet.allOf(Season.class);
System.out.println(es1);
EnumSet es2 = EnumSet.noneOf(Season.class);
System.out.println(es2);
es2.add(Season.WINTER);
es2.add(Season.SPRING);
System.out.println(es2);
//输出summer,winter
EnumSet es3 = EnumSet.of(Season.SUMMER,Season.WINTER);
System.out.println(es3);
//输出summer,fall,winter
EnumSet es4 = EnumSet.range(Season.SUMMER, Season.WINTER);
System.out.println(es4);
//获得es4的余集
EnumSet es5 = EnumSet.complementOf(es4);
//输出spring
System.out.println(es5);
}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值