黑马程序员——JAVA基础------集合框架(二)----Set接口
2015-07-20 14:48
579 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——
一 个 不 包 含 重 复 元 素 的 collection 。更 确 切 地 讲 , set 不 包 含 满 足 el.equaIs(e2) 的 元 素 。对 el 和 e2, 并 且 最 多 包 含 一 个 null 元 素 。 正 如 其 名 称 所 暗 示 的 , 此 接 口 模 仿 了 数 学
上 的set 抽 象 。
类实现Set接口,由哈希表支持。它是无序的,不允许元素的重复,允许使用null 元素。初始容量为16,加载因子为0.75
HashSet是如何保证元素唯一性呢?
是通过元素的两个方法,hashCode 和 equals来完成
如果元素的hashCode值相同,才会判断equals是否为true
如果元素的hashCode值不同,不会调用equals
注意:对于判断元素是否存在,以及删除等操作,依赖来的方法是元素的hashcode和equals方法
代码演示:
基于TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeSet保证元素唯一性的依据:compareTo方法 return 0
第一种排序方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖Comparable方法。这种方式也称为元素的自然顺序,或者叫默认顺序。
第二种排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
当两种排序都存在时,以比较器为主。、
定义一个类,实现Comparator接口,覆盖compare方法
代码演示:
自定义比较器的代码演示:
练习:
具有可预知迭代顺序的set接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重 链接列表。此链接列表定义了迭代顺序,即按照将元素插入到set中的顺序(插入顺序)进行迭代。注意:插入顺序不受在set中重新插入的元素的影响。(如果在s.contains(e)返回true后立即调用s.add(e),则元素e会被重新插入到sets中。)
代码演示:
一、Set接口
1 、 Set 接口
public interface Set<E> extends Collection<E>
一 个 不 包 含 重 复 元 素 的 collection 。更 确 切 地 讲 , set 不 包 含 满 足 el.equaIs(e2) 的 元 素 。对 el 和 e2, 并 且 最 多 包 含 一 个 null 元 素 。 正 如 其 名 称 所 暗 示 的 , 此 接 口 模 仿 了 数 学
上 的set 抽 象 。
2、HashSet 接口
public class HashSet<E> extends AbstractSet<E> implements Cloneable, Serializable
类实现Set接口,由哈希表支持。它是无序的,不允许元素的重复,允许使用null 元素。初始容量为16,加载因子为0.75
HashSet是如何保证元素唯一性呢?
是通过元素的两个方法,hashCode 和 equals来完成
如果元素的hashCode值相同,才会判断equals是否为true
如果元素的hashCode值不同,不会调用equals
注意:对于判断元素是否存在,以及删除等操作,依赖来的方法是元素的hashcode和equals方法
代码演示:
package com.joe.list; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; /** * HashSet实现类: 1、不保证迭代顺序 2、底层使用HashMap实现(哈希表) * 3、自定义对象是否重复的判断条件是:先判断hashCode是否相等,如果hashCode不相等,那么一定不是同一个对象 * 如果hashCode相等,那么就需要equals方法进一步判断,如果equals返回true,表示对象是同一个 * 如果equals返回false,表示对象不是同一个 */ public class SetDemo { public static void main(String[] args) { HashSet<String> hs = new HashSet<String>(); hs.add("大家好"); hs.add("努力"); hs.add("学习"); hs.add("JAVA"); hs.add("ANDROID"); System.out.println("元素的个数是:" + hs.size()); Iterator<String> it = hs.iterator(); while (it.hasNext()) { System.out.println(it.next()); } System.out.println("-------------------------------------"); // ----------存储自定义对象-------------------- HashSet<Person> hs1 = new HashSet<Person>(); Person p1 = new Person("LISI1", 30); Person p2 = new Person("LISI2", 29); Person p3 = new Person("LISI3", 32); Person p4 = new Person("LISHI4", 28); hs1.add(p1); hs1.add(p2); hs1.add(p3); hs1.add(p4); System.out.println("一共有元素:" + hs1.size()); Iterator it1 = hs1.iterator(); while (it1.hasNext()) { Person p = (Person) it1.next(); System.out.println(p); } } } class Person { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public int hashCode() { return name.hashCode() + age * 31; } @Override public boolean equals(Object obj) { if (this==obj) return true; if(obj!=null && obj.getClass() == Person.class){ Person p = (Person) obj; return this.name.equals(p.name) && this.age == p.age; } return false; } 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 String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
3、TreeSet
public class TreeSet<E> extends AbstractSet<E> implements Cloneable, Serializable
基于TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeSet保证元素唯一性的依据:compareTo方法 return 0
第一种排序方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖Comparable方法。这种方式也称为元素的自然顺序,或者叫默认顺序。
第二种排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
当两种排序都存在时,以比较器为主。、
定义一个类,实现Comparator接口,覆盖compare方法
代码演示:
package com.joe.list; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; /** * TreeSet实现类 * 1、使用元素的自然顺序对元素进行排序 * 2、底层使用TreeMap实现(树型结构) * 3、在TreeSet集合中存储自定义对象时,该对象必须实现Comparable/Comparator接口 * 4、底层是自然排序,如果要按照存入的顺序输出,重写compareTo()方法,改为“return 1“,如果要倒序输出,重写compareTo()方法,改为“return -1” */ public class TreeSetDemo { public static void main(String[] args) { Set<String> ts = new TreeSet<String>(); ts.add("小明"); ts.add("小张"); ts.add("小曾"); ts.add("小琪"); System.out.println("元素的个数是:" + ts.size()); Iterator it = ts.iterator(); while (it.hasNext()) { System.out.println(it.next()); } System.out.println("----------添加自定义对象------------"); Set<Student> students = new TreeSet<Student>(); Student s1 = new Student("小明", 30); Student s2 = new Student("小张", 29); Student s3 = new Student("小曾", 32); Student s4 = new Student("小琪", 28); students.add(s1); students.add(s2); students.add(s3); students.add(s4); students.add(new Student("利亚", 29)); System.out.println("元素的个数是:" + students.size()); Iterator<Student> it1 = students.iterator(); while (it1.hasNext()) { System.out.println(it1.next()); } } } class Student implements Comparable { private String name; private int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public Student() { super(); } 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 String toString() { return "Student [name=" + name + ", age=" + age + "]"; } @Override public int compareTo(Object obj) { if (!(obj instanceof Student)) throw new RuntimeException("不是学生对象"); Student s = (Student) obj; if (this.age > s.age) { //先比较年龄 return 1; } else if (this.age < s.age) { return this.name.compareTo(s.name); //如果年龄相同,在比较名字 } return -1; } }
自定义比较器的代码演示:
package com.joe.list; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; /** * 当元素自身不具备比较性,或者具备的比较性不是所需要的。这时需要让容器自身具备比较性。 定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数 * * @author joe * */ public class TreeSetDemo2 { public static void main(String[] args) { TreeSet ts = new TreeSet(new MyCompare()); ts.add(new Student2("lisi",23)); ts.add(new Student2("lisi1",22)); ts.add(new Student2("lisi2",24)); ts.add(new Student2("lisi3",21)); Iterator it = ts.iterator(); while(it.hasNext()){ Student2 stu = (Student2)it.next(); System.out.println(stu.getName()+"..."+stu.getAge()); } } } //自定义比较器 class MyCompare implements Comparator{ public int compare(Object o1,Object o2){ Student2 s1 = (Student2)o1; Student2 s2 = (Student2)o2; int num = s1.getName().compareTo(s2.getName()); if(num==0) { //把int类型封装成Integer对象,调用compareTo方法 return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); // if(s1.getAge()>s2.getAge()) // return 1; // if(s1.getAge()==s2.getAge()) // return 0; // return -1; } return num; } } class Student2 implements Comparable { private String name; private int age; public Student2(String name, int age) { super(); this.name = name; this.age = age; } public Student2() { super(); } 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 String toString() { return "Student [name=" + name + ", age=" + age + "]"; } @Override public int compareTo(Object obj) { if (!(obj instanceof Student2)) throw new RuntimeException("不是学生对象"); Student2 s = (Student2) obj; if (this.age > s.age) { // 先比较年龄 return 1; } else if (this.age < s.age) { return this.name.compareTo(s.name); // 如果年龄相同,在比较名字 } return -1; } }
练习:
package com.joe.list; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; /** * 练习:按照字符串长度排序 * * @author joe * */ public class TreeSetPractice { public static void main(String[] args) { TreeSet ts = new TreeSet(new StrLenComparator()); ts.add("abc"); ts.add("abec"); ts.add("at"); ts.add("abcwrw"); Iterator it = ts.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } class StrLenComparator implements Comparator { //重写compare方法 public int compare(Object o1, Object o2) { String s1 = (String) o1; String s2 = (String) o2; int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); if (num == 0) return s1.compareTo(s2); return num; } }
4、LinkedHashSet
public class LinkedHashSet<E> extends HashSet<E> implements Set<E>,Cloneable,Serializable
具有可预知迭代顺序的set接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重 链接列表。此链接列表定义了迭代顺序,即按照将元素插入到set中的顺序(插入顺序)进行迭代。注意:插入顺序不受在set中重新插入的元素的影响。(如果在s.contains(e)返回true后立即调用s.add(e),则元素e会被重新插入到sets中。)
代码演示:
package com.joe.list; import java.util.LinkedHashSet; import java.util.Set; /* LinkedHashSet实现类 1、使用哈希表+双向链表实现 2、会以插入的顺序输出 3、底层是使用LinkedHashMap实现 * 4、是HashSet的子类 */ public class LinkedHashSetDemo { public static void main(String[] args) { Set<Student> set = new LinkedHashSet<Student>(); Student s1 = new Student("小明", 18); Student s2 = new Student("小张", 19); Student s3 = new Student("小红", 17); set.add(s3); set.add(s2); set.add(s1); set.add(new Student("小红", 17)); System.out.println(set); } } class Student implements Comparable { private String name; private int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public Student() { super(); } 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 String toString() { return "Student [name=" + name + ", age=" + age + "]"; } @Override public int compareTo(Object obj) { if (!(obj instanceof Student)) throw new RuntimeException("不是学生对象"); Student s = (Student) obj; if (this.age > s.age) { // 先比较年龄 return 1; } else if (this.age < s.age) { return this.name.compareTo(s.name); // 如果年龄相同,在比较名字 } return -1; } }
相关文章推荐
- java编程之集合类(一)
- Set集合
- Queue集合
- 程序员跳槽神级攻略
- Android程序员不可错过的十款实用工具
- 黑马程序员---异常处理
- 20150718--面试常见问题(1)
- 黑马程序员-----Java基础
- 面试官最爱提的问题TOP10来自:北京人才市场报
- 黑马程序员--------String类
- 阿里内推面试经验
- 十道海量数据处理面试题与十个方法大总结
- 这些面试机会,你该主动放弃!
- 关于面试的一些事
- Java常用排序算法/程序员必须掌握的8大排序算法
- 黑马程序员————Java基础日常笔记---IO流一
- hibernate面试汇总
- Pocket Gems面试专题
- 第一部分、十道海量数据处理面试题
- (转)第一部分、十道海量数据处理面试题