java 基础 --Collection(Set)
注意:
如果hashSet存储自定义对象,一定要重写hashCode()&&equals()
如果TreeSet存储自定义对象,让元素所属的类实现自然排序接口Comparable,并重写CompareTo()/让集合的构造方法接收一个比较器接口的子类对象Comparator
结构:
Set:
|--HashSet(底层结构是Hash表(Hash表:元素是链表的数组,Hash表依赖于Hash值存储))
|--LinkedHashSet(底层机构是链表和Hash表)
|--TreeSet(底层是二叉树结构(红黑树是一种自平衡的二叉树)) 详解:
Set
无序(存储顺序和取出顺序不一致),唯一(虽然set集合的元素无序,但是作为集合来说肯定有它的存储顺序,而你的存储顺序和它的顺序一致,这代表不了有序。)
|-- HashSet
HashSet底层依赖的是hashCode()和equals()
所以存储自定义对象时,对象需要重写hashCode()和equals()来保证唯一性(自动重写即可) HashSet 底层源码:
①HashSet<String> set = new HashSet<String>();
public HashSet() {
map = new HashMap<>();
}
②set.add("atomic");
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
源码结论:HashSet是一个HashMap,它的值存储在HashMap的Key中,因此hashSet数据是唯一的 if (e.hash == hash && //先看hashCode(),如果hash值相同,不添加元素
((k = e.key) == key || (key != null && key.equals(k)))){break;} //如果元素值/地址值相同(元素重复),也不添加元素
p = e;//以上三种情况外才添加元素 TreeSet:自然排序,唯一(TreeSet底层就是treeMap)
API: A NavigableSet implementation based on a TreeMap
①如果是基本类型,会自动进行排序,去重
②如果是自定义类型,需要重写...
真正的比较依赖于元素的CompareTo()方法,而这个方法是定义在Comparable里面的,
所以要想重写该方法,就必须先实现COmparable接口,这个接口表示的就是自然排序
底层是二叉树结构(红黑树是一种自平衡的二叉树)。
二叉树三种遍历:
中序遍历:先左子树,后根节点,再右子树
前序遍历:先根节点,后左子树,再右子树
后序遍历:先左子树,后右子树,再根节点 源码:①TreeSet<String> set = new TreeSet<String>();
②set.add("d"); public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
private transient NavigableMap<E,Object> m;
API: A NavigableSet implementation based on a TreeMap TreeMap的put();
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);//key-t.key
if (cmp < 0) // key小放左边
t = t.left;
else if (cmp > 0) // key大放右边
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;
}
总结:TreeSet集合保证元素排序和唯一性的原理
唯一性:根据比较的返回值是否为0来决定的
排序:
A:自然排序(元素具备比较性)
让元素所属的类实现自然排序接口Comparable
B:比较器排序(集合具备比较性)
让集合的构造方法接收一个比较器接口的子类对象Comparator
举例:A:
// 方式1:
TreeSet<Student> ts1 = new TreeSet<Student>();
// 如果一个类想要进行自然排序,就必须实现自然排顺序接口
public class Student implements Comparable<Student>{
private String name;
private int age;
@Override
public int compareTo(Student o) {
// 按年龄,主要条件
int num = this.age - o.age;
// 次要条件,年龄相同时好要看名字是否相同
// 如果名字和年龄都相同,才是一个元素
int num2 = num == 0?this.name.compareTo(o.name):num;
return num2; /* 按名字排序
@Override
public int compareTo(Student o) {
// 按姓名,主要条件
int num = this.name.length() - o.name.length();
// 姓名长度相同不代表内容相同
int num2 = num == 0?this.name.compareTo(o.name):num;
// 姓名长度和内容相同,不代表年龄相同
int num3 = num2 == 0?this.age-o.age:num2;
return num3;
}
*/
} B:
//方式2
TreeSet<Student> ts2 = new TreeSet<Student>(new MyComparator());
// 实现Comparator()接口
public class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
// 按姓名,主要条件
int num = o1.getName().length() - o2.getName().length();
// 姓名长度相同不代表内容相同
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
// 姓名长度和内容相同,不代表年龄相同
int num3 = num2 == 0 ? o1.getAge() - o2.getAge() : num2;
return num3;
}
}
//方式3(匿名类方式)
TreeSet<Student> ts3 = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// 按姓名,主要条件
int num = o1.getName().length() - o2.getName().length();
// 姓名长度相同不代表内容相同
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
// 姓名长度和内容相同,不代表年龄相同
int num3 = num2 == 0 ? o1.getAge() - o2.getAge() : num2;
return num3;
}
});
java 基础 --Collection(Set)的更多相关文章
- Java基础-Collection子接口之Set接口
Java基础-Collection子接口之Set接口 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 学习Collection接口时,记得Collection中可以存放重复元素,也可 ...
- Java基础-Collection子接口之List接口
Java基础-Collection子接口之List接口 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们掌握了Collection接口的使用后,再来看看Collection接口中 ...
- Java基础 -- Collection和Iterator接口的实现
Collection是描述所有序列容器(集合)共性的根接口,它可能被认为是一个“附属接口”,即因为要表示其他若干个接口的共性而出现的接口.另外,java.util.AbstractCollection ...
- Java基础——collection接口
一.Collection接口的定义 public interfaceCollection<E>extends iterable<E> 从接口的定义中可以发现,此接口使用了泛型 ...
- Java 基础 - Collection集合通用方法及操作/ArrayList和LinkedList的差别优势 /弃用的Vector
Collection的笔记: /**存储对象考虑使用: * 1.数组, ①一旦创建,其长度不可变!② 长度难于应对实际情况 * 2.Java集合, ①Collection集合: 1.set: 元素无序 ...
- java基础- Collection和map
使用构造方法时,需要保留一个无参的构造方法 静态方法可以直接通过类名来访问,而不用创建对象. -- Java代码的执行顺序: 静态变量初始化→静态代码块→初始化静态方法→初始化实例变量→代码块→构造方 ...
- java 基础 --Collection(Map)
Map是不是集合?哈哈哈 java编程思想>的第11章,第216页,正数第13行,中原文:“……其中基本的类型是LIst.Set.Queue和Map.这些对象类型也称为集合类,但由于Java类库 ...
- Java基础Collection集合
1.Collection是所有集合的父类,在JDK1.5之后又加入了Iterable超级类(可以不用了解) 2.学习集合从Collection开始,所有集合都继承了他的方法 集合结构如图:
- JAVA基础第四章-集合框架Collection篇
业内经常说的一句话是不要重复造轮子,但是有时候,只有自己造一个轮子了,才会深刻明白什么样的轮子适合山路,什么样的轮子适合平地! 我将会持续更新java基础知识,欢迎关注. 往期章节: JAVA基础第一 ...
随机推荐
- 763. Hex Conversion [LintCode naive]
Description Given a decimal number n and an integer k, Convert decimal number n to base-k. 1.0<=n ...
- 《Java核心技术36讲》阅读笔记:谈谈对Java平台的理解笔记
1. 谈谈你对Java平台的理解. Java是一种面向对象的语言,最显著的特性有两个方面: 一个就是一次编译,到处运行(Write once, run anywhere),能够非常容易的获得跨平台能力 ...
- 安装虚拟机及学习linux系统 20155222卢梓杰
安装虚拟机及学习linux系统 20155222卢梓杰 首先按照要求下载virtualbox,没有遇到问题. 接下来新建一个虚拟机,按照要求应当安装乌班图64,这里只有32位的.在网上搜寻了许久,终于 ...
- 20155231 cho3 课下作业
20155231 cho3 课下作业 4 1 通过输入gcc -S -o main.s main.c 将下面c程序"week0603学号.c"编译成汇编代码 int g(int x ...
- 20155323 2016-2017-2 《Java程序设计》第3周学习总结
20155323 2016-2017-2 <Java程序设计>第3周学习总结 教材学习内容总结 第四章 对象:对象具有状态和行为,对象是类的实例. 类:一个类可以被定义为描述行为的模板. ...
- 20155331 实验四 Android开发基础
20155331丹增旦达实验四报告 实验四 Android程序设计-1 Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBIT,Java ...
- Spring学习(十)-----Spring依赖检查
在Spring中,可以使用依赖检查功能,以确保所要求的属性可设置或者注入. 依赖检查模式 4个依赖检查支持的模式: none – 没有依赖检查,这是默认的模式. simple – 如果基本类型(int ...
- jquery Ajax请求中显示Loading...
jquery Ajax请求中显示Loading... $('#btnTest').click(function(){ $.ajax({ url ---- ,根据你需要设置 ...
- Scala基础知识笔记2
1 类 1.1 定义一个简单的类 1.2 field的getter 和 setter方法 感觉成员变量定义成 var 属性名=属性值即可, 不需要定义成 val 或者 private就行, // ...
- 设置PNG图片DPI 信息,保存为PDF(使用Magick),与OpenCV转换
目录 任务描述 解决方案 Magick++ Talk is cheap, show me the code. 与 Opencv 配合 相关链接 任务描述 我有这样一个需求,读取一张格式为PNG 或者 ...