Java集合框架总结之Set接口的使用
2015-11-09 10:16
561 查看
List接口和Set接口都继承自Collection接口,区别如下:
List中的元素有序,且可以重复,元素可以用下标操作
Set中的元素无序,且不能重复,元素无法用下标操作
下面我们仅仅介绍Set接口的使用,List接口的使用请参考:
http://blog.csdn.net/u011983531/article/details/49735115
注:Set中的元素无法用下标操作
(1)添加
(2)删除
(3)查找
(4)其他操作
注意:由于Set中的元素是不重复的,所以在添加元素时,需要判断Set中是否有该元素。下面的HashSet的TreeSet详细介绍了如何保证Set中的元素不重复。
TreeSet:内部数据结构是二叉排序树,是线程不安全的。
1、HashSet
HashSet的内部数据结构是哈希表,下面是哈希表确定元素是否相同的方法:
首先判断的是两个对象的哈希值是否相同,如果相同,再判断两个对象的内容是否相同。
注:判断哈希值是否相同,其实是判断对象的hashCode()方法的返回结果是否相同;判断内容是否相同,用的是对象的equals()方法。如果哈希值不相同,不需要判断equals()方法。
所以,在使用HashSet存储对象时,必须实现对象的hashCode()方法和equals()方法。
举例说明:
如果Person类没有重写hashCode()和equals()方法,或者只重写了其中一个,[zhangsan,21]这条记录都会被添加两次。
2、TreeSet
TreeSet判断元素是否相同的方法:
根据比较方法的返回结果来判断,如果是0,就是相同元素,不存储,否则就是不同元素。
所以,在使用TreeSet存储对象时,要么对象实现Comparable接口,要么定义在创建TreeSet时,传入比较器。
(1)实现Comparable举例:
如果Person类没有实现Comparable接口,运行过程中就会出现类型转换异常。
(2)使用比较器举例
List中的元素有序,且可以重复,元素可以用下标操作
Set中的元素无序,且不能重复,元素无法用下标操作
下面我们仅仅介绍Set接口的使用,List接口的使用请参考:
http://blog.csdn.net/u011983531/article/details/49735115
一、Set接口的常见操作
因为我们经常使用Set接口来操作它的实现类(如:HashSet)的对象,所以对Set接口中常见的操作,一定要非常熟悉。注:Set中的元素无法用下标操作
(1)添加
//如果set 中尚未存在指定的元素,则添加此元素 boolean add(E e) //如果set 中没有指定collection 中的所有元素,则将其添加到此set 中 boolean addAll(Collection<? extends E> c)
(2)删除
//移除此 set 中的所有元素 void clear() //如果 set 中存在指定的元素,则将其移除 boolean remove(Object o) //移除 set 中那些包含在指定 collection 中的元素 boolean removeAll(Collection<?> c)
(3)查找
//返回在此 set 中的元素上进行迭代的迭代器 Iterator<E> iterator()
(4)其他操作
//返回set中的元素数 int size() //判断set是否为空,如果set不包含元素,则返回 true boolean isEmpty() //判断集合中是否包含指定的元素 boolean contains(Object o) //如果此 set 包含指定 collection 的所有元素,则返回 true boolean containsAll(Collection<?> c) //返回一个包含set中所有元素的数组 Object[] toArray()
注意:由于Set中的元素是不重复的,所以在添加元素时,需要判断Set中是否有该元素。下面的HashSet的TreeSet详细介绍了如何保证Set中的元素不重复。
二、Set接口常见子类
HashSet:内部数据结构是哈希表,是线程不安全的。TreeSet:内部数据结构是二叉排序树,是线程不安全的。
1、HashSet
HashSet的内部数据结构是哈希表,下面是哈希表确定元素是否相同的方法:
首先判断的是两个对象的哈希值是否相同,如果相同,再判断两个对象的内容是否相同。
注:判断哈希值是否相同,其实是判断对象的hashCode()方法的返回结果是否相同;判断内容是否相同,用的是对象的equals()方法。如果哈希值不相同,不需要判断equals()方法。
所以,在使用HashSet存储对象时,必须实现对象的hashCode()方法和equals()方法。
举例说明:
package com.ghs.test; import java.util.HashSet; import java.util.Set; public class TestHashSet { public static void main(String[] args) { Set<Person> persons = new HashSet<Person>(); persons.add(new Person("zhangsan", 21)); persons.add(new Person("lisi", 21)); persons.add(new Person("zhangsan", 21)); persons.add(new Person("wangwu", 21)); System.out.println(persons.size()); } } class Person{ private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } //当name和age都相同时,表示是同一个人 @Override public int hashCode() { return this.name.hashCode() + age*31; } @Override public boolean equals(Object obj) { if( this ==obj) return true ; if(!(obj instanceof Person) ) throw new ClassCastException(); Person person = (Person) obj; return this.name.equals(person.getName()) && this.age==person.getAge(); } }
如果Person类没有重写hashCode()和equals()方法,或者只重写了其中一个,[zhangsan,21]这条记录都会被添加两次。
2、TreeSet
TreeSet判断元素是否相同的方法:
根据比较方法的返回结果来判断,如果是0,就是相同元素,不存储,否则就是不同元素。
所以,在使用TreeSet存储对象时,要么对象实现Comparable接口,要么定义在创建TreeSet时,传入比较器。
(1)实现Comparable举例:
package com.ghs.test; import java.util.Set; import java.util.TreeSet; public class TestTreeSet { public static void main(String[] args) { Set<Person> persons = new TreeSet<Person>(); persons.add(new Person("zhangsan", 21)); persons.add(new Person("lisi", 21)); persons.add(new Person("zhangsan", 21)); persons.add(new Person("wangwu", 21)); System.out.println(persons.size()); } } class Person implements Comparable{ private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } /** * 比较的主要条件:姓名 * 次要条件:年龄 */ @Override public int compareTo(Object obj) { if(!(obj instanceof Person) ) throw new ClassCastException(); Person person = (Person) obj; int temp = this.name.compareTo(person.getName()); return temp ==0 ? this.age-person.getAge() :temp ; } }
如果Person类没有实现Comparable接口,运行过程中就会出现类型转换异常。
(2)使用比较器举例
package com.ghs.test; import java.util.Comparator; import java.util.Set; import java.util.TreeSet; public class TestTreeSet2 { public static void main(String[] args) { Set<Person> persons = new TreeSet<Person>(new PersonComparator()); persons.add(new Person2("zhangsan", 21)); persons.add(new Person2("lisi", 21)); persons.add(new Person2("zhangsan", 21)); persons.add(new Person2("wangwu", 21)); System.out.println(persons.size()); } } class Person{ private String name; private int age; public Person2(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } class PersonComparator implements Comparator{ @Override public int compare(Object obj1, Object obj2) { if(!(obj1 instanceof Person) ) throw new ClassCastException(); if(!(obj2 instanceof Person) ) throw new ClassCastException(); Person person1 = (Person) obj1; Person person2 = (Person) obj2; int temp = person1.getName().compareTo( person2.getName()) ; return temp == 0 ? person1.getAge()-person2.getAge():temp ; } }
三、遍历Set中的元素
遍历Set中的元素有两种方法,一种是使用迭代器,另一种是直接使用增强for循环,但是不能用下标操作。//遍历 public static void testSet(){ HashSet<Person> persons = new HashSet<Person>(); persons.add(new Person("zhangsan", 21)); persons.add(new Person("lisi", 21)); persons.add(new Person("wangwu", 21)); //方法一:迭代器 Iterator<Person> it = persons.iterator(); for(Person p = it.next() ; it.hasNext();){ System.out.println(p.getName() +"----"+p.getAge()); } //或者 while(it.hasNext()){ Person p = (Person) it.next() ; System.out.println(p.getName() +"----"+p.getAge()); } //方法二:for循环 for(Person p : persons){ System.out.println(p.getName() +"----"+p.getAge()); } }
相关文章推荐
- set 命令特殊用法
- You must SET PASSWORD before executing this statement的解决方法
- 批处理 Set 命令详解 让你理解set命令第1/2页
- ASP中set与dim的区别(自己的理解)
- 深入C#中get与set的详解
- sql Set IDENTITY_INSERT的用法
- set_include_path在win和linux下的区别
- jquery中常用的SET和GET
- 大家注意vector, list, set, map成员函数erase
- 基于SQL中SET与SELECT赋值的区别详解
- mysql之set与enum的介绍
- php set_magic_quotes_runtime() 函数过时解决方法
- MySQL的FIND_IN_SET函数使用方法分享
- .net get set用法小结第1/3页
- mysqli_set_charset和SET NAMES使用抉择及优劣分析
- asp.net get set用法第1/2页
- java比较器comparator使用示例分享
- Java 中Comparable和Comparator区别比较
- Java集合类中文介绍
- Mysql中的find_in_set的使用方法介绍