package cn.temptation;

 import java.util.HashSet;
import java.util.Set; public class Sample01 {
public static void main(String[] args) {
/*
* 接口 Set<E>:一个不包含重复元素的 collection。
*
* 特点:
* 1、无序:指的是Set显示其元素的顺序 与 放入元素的顺序可能不一致
* 2、唯一:放入其中的元素是唯一的
*/ Set<String> set = new HashSet<>(); set.add("China");
set.add("USA");
set.add("Japan");
set.add("China"); System.out.println("set:" + set); // set:[USA, China, Japan] // 通过查看源码,发现会使用到元素的hashCode,hashCode相同的字符串添加时不重复添加
System.out.println("China".hashCode()); //
System.out.println("USA".hashCode()); //
System.out.println("Japan".hashCode()); //
System.out.println((new String("China")).hashCode()); //
}
}
// 查看HashSet类的源码
//public boolean add(E e) {
// return map.put(e, PRESENT)==null;
//} //private transient HashMap<E,Object> map; // 查看HashMap类的源码
//public V put(K key, V value) {
// return putVal(hash(key), key, value, false, true);
//}
 package cn.temptation;

 import java.util.HashSet;
import java.util.Set; public class Sample02 {
public static void main(String[] args) {
// 类 HashSet<E>:此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。
// 它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。 Set<Student> set = new HashSet<>(); set.add(new Student("张三", 18));
set.add(new Student("李四", 20));
set.add(new Student("王五", 22));
set.add(new Student("张三", 18)); // 分析:观察一下创建相同姓名、相同年龄的学生对象,它们的hashCode是否一致
// 原因在于因为Student类的对象没有重写hashCode方法和equals方法,默认使用Object类的hashCode方法和equals方法 System.out.println((new Student("张三", 18)).hashCode()); // 未重写时的值:118352462 重写后的值:776408
System.out.println((new Student("张三", 18)).hashCode()); // 未重写时的值:1550089733 重写后的值:776408 System.out.println("set:" + set);
}
}
 package cn.temptation;

 import java.util.LinkedHashSet;
import java.util.Set; public class Sample03 {
public static void main(String[] args) {
/*
* 类 LinkedHashSet<E>:具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。
*
* 特点:有序唯一
* 1、唯一:通过哈希表来保证唯一
* 2、有序:通过链表来保证元素的有序
*/
Set<String> set = new LinkedHashSet<>(); set.add("China");
set.add("USA");
set.add("Japan");
set.add("China");
set.add("France");
set.add("England"); System.out.println("set:" + set);
}
}
 package cn.temptation;

 import java.util.Set;
import java.util.TreeSet; public class Sample04 {
public static void main(String[] args) {
/*
* 类 TreeSet<E>:
* 基于 TreeMap 的 NavigableSet 实现。
* 使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
*
* 能够对其中的元素按照某种规则进行排序
*
* 某种规则:
* 1、可以按照自然顺序规则
* 2、可以按照自定义排序规则
*/ // 1、自然排序规则
Set<Integer> set1 = new TreeSet<>(); set1.add(1);
set1.add(3);
set1.add(2);
set1.add(4); System.out.println("treeset:" + set1); // treeset:[1, 2, 3, 4] System.out.println("-------------------------------------------"); Set<Character> set2 = new TreeSet<>(); set2.add('j');
set2.add('A');
set2.add('v');
set2.add('a');
set2.add('G');
set2.add('O');
set2.add('o');
set2.add('D'); System.out.println("treeset:" + set2); // treeset:[A, D, G, O, a, j, o, v] System.out.println("-------------------------------------------"); Set<String> set3 = new TreeSet<>(); set3.add("USA");
set3.add("China");
set3.add("Japan");
set3.add("Chile"); System.out.println("treeset:" + set3); // treeset:[Chile, China, Japan, USA] System.out.println("-------------------------------------------"); Set<String> set4 = new TreeSet<>(); set4.add("张三");
set4.add("李四");
set4.add("王五");
set4.add("张飞"); System.out.println("treeset:" + set4); // treeset:[张三, 张飞, 李四, 王五] 显然不是根据拼音的顺序 System.out.println((int)'张' + " VS " + (int)'李' + " VS " + (int)'王'); // 24352 VS 26446 VS 29579
System.out.println((int)'三' + " VS " + (int)'飞'); // 19977 VS 39134
}
}
 package cn.temptation;

 import java.util.Set;
import java.util.TreeSet; public class Sample05 {
public static void main(String[] args) {
// 可以按照自定义排序规则 // 思路:
// 考虑到Set容器中的元素是无序且唯一的,要让他们可以有顺序,其实就是让它们具备可比较的能力,即实现Comparable<T>接口 /*
* 接口 Comparable<T>:此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
*
* Comparable<T>接口的常用成员方法:
* int compareTo(T o) :比较此对象与指定对象的顺序。
*/ Set<Student> set = new TreeSet<>(); // 执行异常:java.lang.ClassCastException: cn.temptation.Student cannot be cast to java.lang.Comparable
set.add(new Student("张三", 20));
set.add(new Student("李四", 18));
set.add(new Student("王五", 22));
set.add(new Student("张飞", 20)); for (Student item : set) {
System.out.println(item);
}
}
}
 package cn.temptation;

 import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet; public class Sample06 {
public static void main(String[] args) {
/*
* 接口 Comparator<T>:
* 强行对某个对象 collection 进行整体排序 的比较函数。
* 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
* 还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。
*/ /*
* TreeSet类的构造函数:
* TreeSet(Comparator<? super E> comparator) :构造一个新的空 TreeSet,它根据指定比较器进行排序。
*/ // 创建比较器对象
Comparator<Student> comparator = new StudentCompartor(); Set<Student> set = new TreeSet<>(comparator); set.add(new Student("张三", 20));
set.add(new Student("李四", 18));
set.add(new Student("王五", 22));
set.add(new Student("张飞", 20)); for (Student item : set) {
System.out.println(item);
}
}
}
 package cn.temptation;

 import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet; public class Sample07 {
public static void main(String[] args) {
// 观察到TreeSet类的构造函数TreeSet(Comparator<? super E> comparator) :构造一个新的空 TreeSet,它根据指定比较器进行排序。
// 传入的是一个接口,所以考虑使用匿名内部类
// 匿名内部类写法的优点:使用了匿名内部类,就不用再制作实现Comparator接口的实现类了 Set<Student> set = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student student1, Student student2) {
// 首先按年龄的自然顺序
int resultAge = student1.getAge() - student2.getAge(); /*
* 其次按姓名的自然顺序
* 字符串的比较时,考虑使用String类的compareTo方法
* String类的常用成员方法:
* int compareTo(String anotherString) :按字典顺序比较两个字符串。
*/
int result = (resultAge == 0) ? student1.getName().compareTo(student2.getName()) : resultAge; return result;
}
}); set.add(new Student("张三", 20));
set.add(new Student("李四", 18));
set.add(new Student("王五", 22));
set.add(new Student("张飞", 20)); for (Student item : set) {
System.out.println(item);
}
}
}
 package cn.temptation;

 import java.util.Set;
import java.util.TreeSet; public class Sample08 {
public static void main(String[] args) {
Set<Integer> set = new TreeSet<>(); set.add(1);
set.add(5);
set.add(4);
set.add(2);
set.add(3); for (Integer item : set) {
System.out.println(item);
}
}
}
// 【TreeSet存储规则】
// 第一个元素存储时,直接作为根节点存储
// 从第二个元素开始,每个元素存储时从根节点开始比较
// 如果比根节点大,就作为根节点的右侧
// 如果比根节点小,就作为根节点的左侧
// 如果相等,就无视
// 【TreeSet取出规则】
// 取出时,根据(前序遍历、中序遍历、后序遍历)
// 从根节点开始,按照左、中、右的原则依次取出元素 // 查看TreeSet类的源码
//public boolean add(E e) {
// return m.put(e, PRESENT)==null;
//} //private transient NavigableMap<E,Object> m; //查看TreeMap类的源码
//public V put(K key, V value) {
// Entry<K,V> t = root;
// if (t == null) {
// compare(key, key); // type (and possibly null) check
//
// root = new Entry<>(key, value, null);
// size = 1;
// modCount++;
// return null;
// }
// int cmp;
// Entry<K,V> parent;
// // split comparator and comparable paths
// Comparator<? super K> cpr = comparator;
// if (cpr != null) {
// do {
// parent = t;
// cmp = cpr.compare(key, t.key);
// if (cmp < 0)
// t = t.left;
// else if (cmp > 0)
// t = t.right;
// else
// return t.setValue(value);
// } while (t != null);
// }
// else {
// if (key == null)
// throw new NullPointerException();
// @SuppressWarnings("unchecked")
// Comparable<? super K> k = (Comparable<? super K>) key;
// do {
// parent = t;
// cmp = k.compareTo(t.key);
// if (cmp < 0)
// t = t.left;
// else if (cmp > 0)
// t = t.right;
// else
// return t.setValue(value);
// } while (t != null);
// }
// Entry<K,V> e = new Entry<>(key, value, parent);
// if (cmp < 0)
// parent.left = e;
// else
// parent.right = e;
// fixAfterInsertion(e);
// size++;
// modCount++;
// return null;
//}
 package cn.temptation;

 // 注意:只定义Student类,放入到TreeSet集合中会产生执行异常:java.lang.ClassCastException: cn.temptation.Student cannot be cast to java.lang.Comparable
//public class Student {
public class Student implements Comparable<Student> {
// 成员变量
private String name;
private int age; // 构造函数
public Student() {
super();
} public Student(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;
} // 为了去除重复内容的对象,需要重写hashCode方法和equals方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
} @Override
public String toString() {
return "学生 [姓名为:" + name + ", 年龄为:" + age + "]";
} // 需要重写compareTo方法进行比较
// 制定比较的规则:先比较年龄的大小,年龄相同时比较姓名的顺序
@Override
public int compareTo(Student anotherStudent) {
// 首先按年龄的自然顺序
int resultAge = this.age - anotherStudent.age; /*
* 其次按姓名的自然顺序
* 字符串的比较时,考虑使用String类的compareTo方法
* String类的常用成员方法:
* int compareTo(String anotherString) :按字典顺序比较两个字符串。
*/
int result = (resultAge == 0) ? this.name.compareTo(anotherStudent.name) : resultAge; return result;
}
}
 package cn.temptation;

 import java.util.Comparator;

 /**
* 实现比较器的类
* 这里没有在Student类上直接实现Comparator<T>接口,是因为Comparator<T>接口的compare方法比较的是两个对象
*
* Comparator<T>接口的常用成员方法:
* 1、int compare(T o1, T o2) :比较用来排序的两个参数。
* 2、boolean equals(Object obj) :指示某个其他对象是否“等于”此 Comparator。
*
* 注意:因为Object基类就有equals方法,所以不显式进行重写,就是使用Object基类的equals方法,不会提示语法出错
*/
public class StudentCompartor implements Comparator<Student> {
/*
* 重写进行比较的方法
* 制定比较的规则:先比较年龄的大小,年龄相同时比较姓名的顺序
*/
@Override
public int compare(Student student1, Student student2) {
// 首先按年龄的自然顺序
int resultAge = student1.getAge() - student2.getAge(); /*
* 其次按姓名的自然顺序
* 字符串的比较时,考虑使用String类的compareTo方法
* String类的常用成员方法:
* int compareTo(String anotherString) :按字典顺序比较两个字符串。
*/
int result = (resultAge == 0) ? student1.getName().compareTo(student2.getName()) : resultAge; return result;
}
}

【原】Java学习笔记028 - 集合的更多相关文章

  1. Java学习笔记之---集合

    Java学习笔记之---集合 (一)集合框架的体系结构 (二)List(列表) (1)特性 1.List中的元素是有序并且可以重复的,成为序列 2.List可以精确的控制每个元素的插入位置,并且可以删 ...

  2. 【原】Java学习笔记026 - 集合

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 需求:从三国演义中 ...

  3. Java学习笔记之集合

    集合(Collection)(掌握) (1)集合的由来? 我们学习的是Java -- 面向对象 -- 操作很多对象 -- 存储 -- 容器(数组和StringBuffer) -- 数组而数组的长度固定 ...

  4. java学习笔记之集合家族2

    集合体系 一.数据结构 List集合储存数据结构 <1>堆栈结构 特点:先进后出 <2>队列结构 特点:先进先出 <3>数组结构 特点:查询快,增删慢 <4& ...

  5. 【Java学习笔记】集合转数组---toArray()

    package p2; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ...

  6. 【Java学习笔记】<集合框架>定义功能去除ArrayList中的重复元素

    import java.util.ArrayList; import java.util.Iterator; import cn.itcast.p1.bean.Person; public class ...

  7. java学习笔记之集合家族1

    集合 集合介绍: 由于数组中存放对象,对对象操作起来不方便.java中有一类容器,专门用来存储对象. 集合与数组的区别: 1.数组的长度固定的,而集合长度时可变的 2.数组只能储存同一类型的元素,而且 ...

  8. 5.3类集(java学习笔记)集合的输出

    一.集合的输出 迭代输出:Iteratror接口 在输出集合时,最标准的方法是使用迭代器迭代输出. 1,List中的迭代器. Iterator中包含三个方法: hasNex()t判断集合内是否有元素存 ...

  9. java学习笔记——Collection集合接口

    NO 方法名称 描述 1 public boolean add(E e) 向集合中保存数据 2 public void clear() 清空集合 3 public boolean contains(O ...

随机推荐

  1. ABP官方文档翻译 4.5 特征管理

    特征管理 介绍 关于IFeatureValueStore 特征类型 Boolean特征 Value特征 定义特征 基本特征属性 其他特征属性 特征层级 检查特征 使用RequiresFeature特性 ...

  2. BZOJ 2938: [Poi2000]病毒 [AC自动机 拓扑排序]

    2938: [Poi2000]病毒 题意:判断是否存在无限长的不含模式串的字符串.只有01. 建出套路DP的转移图,判断有环就行了 练习一下拓扑排序 #include <iostream> ...

  3. Javascript原型继承容易忽略的错误

    编写Javascript的开发者都知道,JS虽然没有类(ES6添加了class语法),但是可以模拟出OOP语言的类和面向对象的概念,比如我们都知道的一句话,Javascript中处处是对象,而面向对象 ...

  4. Spring bean的生命周期详解

    bean的生命周期1.实例化bean 即new2.按照spring上下文对实例化的bean进行配置 即填充属性,也就是IOC/DI(控制反转,依赖注入)3.如果这个bean实现了BeanNameAwa ...

  5. HashMap中的散列函数、冲突解决机制和rehash

    一.概述 散列算法有两个主要的实现方式:开散列和闭散列,HashMap采用开散列实现. HashMap中,键值对(key-value)在内部是以Entry(HashMap中的静态内部类)实例的方式存储 ...

  6. 装x玩法:插上你的专有U盘才能开机

    玩法的效果是这样的: 1.插上你的专有U盘,按电脑开机按钮,电脑正常启动运行: 2.如果不插专有优U盘,按电脑开机按钮,进入桌面后1秒钟电脑自动关机,无法使用.也就是说,没有优U盘将无法使用你的电脑. ...

  7. 【学习笔记】Struts2 类型转换

    为什么需要类型转换 在基于HTTP协议的Web应用中 客户端请求的所有内容(表单中提交的内容等)都以文本编码的方式传输到服务器端但服务器端的编程语言(如Java)有着丰富的数据类型 如 int boo ...

  8. 注册表命令 regedit32

    转自 https://zhidao.baidu.com/question/1958216489744783460.html Regedt32.exe 不支持注册表项文件 (.reg) 的导入和导出. ...

  9. try{}里有一个 return 语句,那么紧跟在这个 try 后的 finally {}里的 code 会 不会被执行,什么时候被执行,在 return 前还是后?

    这是一道面试题,首先finally{}里面的code肯定是会执行的,至于在return前还是后, 看答案说的是在return后执行,我觉得不对,百度了一下,有说return前的,有说return后的, ...

  10. 在Ubuntu上安装PHPStudy组件

    phpStudy for Linux (lnmp+lamp一键安装包) phpStudy Linux版&Win版同步上线 支持Apache/Nginx/Tengine/Lighttpd/IIS ...