1、Set集合(理解)

  (1)Set集合的特点

    无序,唯一。

  (2)HashSet集合(掌握)

    A: 底层数据结构是哈希表(是一个元素为链表的数组)

    B: 哈希表底层依赖两个方法: hashCode() 和 equals()

      执行顺序:

        首先比较哈希值是否相同

          相同:继续执行equals()方法

            返回true:元素重复了,不添加

            返回false:直接把元素添加到集合

          不同:就直接把元素添加到集合

1、人的类

 package com.wyh.hashSet;

 /**
* @author WYH
* @version 2019年11月17日 上午9:21:02
*/
public class Person {
private String name;
private int age; public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
} 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;
Person other = (Person) 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;
} }

2、测试类:

 package com.wyh.hashSet;

 import java.util.HashSet;

 /**
* @author WYH
* @version 2019年11月17日 上午9:21:16
*/
public class HashSetDemo01 {
public static void main(String[] args) {
//创建HashSet集合
HashSet<Person> hs = new HashSet<Person>(); //创建Person类
Person p1 = new Person("小虎",22);
Person p2 = new Person("小强",23);
Person p3 = new Person("小虎",22);
Person p4 = new Person("小美",21);
Person p5 = new Person("小雪",21); //将对象添加到HashSet中去
hs.add(p1);
hs.add(p2);
hs.add(p3);
hs.add(p4);
hs.add(p5); //遍历
for(Person p : hs) {
System.out.println(p.getName()+"---"+p.getAge()); }
} }

3、如下图,如果不重写hashCode()方法和equals()方法,运行结果,可以运行不报错,但是重复的元素也加入了。

4、重写后:

    C:如何保证元素的唯一性呢?

      由hashCode()和equals()保证的(如下图,流程)

    D:开发的时候,代码非常的简单,自动生成即可。

    E:HashSet存储字符串并遍历

 package com.wyh.set;

 import java.util.HashSet;

 /**
* @author WYH
* @version 2019年11月16日 下午7:42:24
*
* HashSet在存储字符串的时候,为什么只存储相同的字符串只存储一个呢?
* 通过查看add方法的源码,我们发现这个方法的底层方法是依赖两个方法,hashCode()和equals()
*
*
*/
public class HashSetDemo01 {
public static void main(String[] args) {
HashSet<String> hs = new HashSet<String>(); hs.add("Hello");
hs.add("World");
hs.add("Java");
hs.add("World"); for(String s : hs) {
System.out.println(s);
} } }

    F:HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素)

  (3)TreeSet集合

    A:底层数据结构是红黑树(是一个自平衡的二叉树)

    B:  保证元素的排序方式

      a: 自然排序(元素具备比较性)

        让元素所属的类实现Comparable接口(难点,需求会给出主要条件,但是需要我们分析次要条件,例如 需求是根据年龄的长度进行排序,但是我们还要考虑姓名的长度和内容)

学生类:

 package com.wyh.treeSet;

 /**
* @author WYH
* @version 2019年11月17日 上午11:13:45
*/
public class Student2 implements Comparable<Student2>{
private String name;
private int age;
public Student2(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student2() {
super();
// TODO Auto-generated constructor stub
}
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(Student2 s) {
int num = this.name.length() - s.name.length();
//次要条件1 姓名长度一样,内容不一定一样
int num2 = num == 0 ? (this.name.compareTo(s.name)) : num;
//次要条件2 姓名长度和内容一样,年龄不一定一样
int num3 = num2 == 0 ? this.age - s.age : num2;
return num3; } }

测试类:

如果不重写自然排序方法,就会报错,因为没有给定如何排序,也没有保证唯一性
// java.lang.ClassCastException: com.wyh.treeSet.Student cannot be cast to
// java.lang.Comparable

 package com.wyh.treeSet;

 import java.util.TreeSet;

 /**
* @author WYH
* @version 2019年11月17日 下午2:27:13
*
* 根据年龄的长度进行排序
*/
public class TreeSetDemo03 {
public static void main(String[] args) {
TreeSet<Student2> ts = new TreeSet<Student2>(); // 创建学生对象
Student2 s1 = new Student2("王友虎", 22);
Student2 s2 = new Student2("赵以浩", 24);
Student2 s3 = new Student2("齐博源", 21);
Student2 s4 = new Student2("李先锋", 23);
Student2 s5 = new Student2("李宏灿", 22);
Student2 s6 = new Student2("薛长城", 23);
Student2 s7 = new Student2("黄天祥", 24);
Student2 s8 = new Student2("王友虎", 23); // 添加到TreeSet中
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
ts.add(s8); // 遍历
// 如果不重写自然排序方法,就会报错,因为没有给定如何排序,也没有保证唯一性
// java.lang.ClassCastException: com.wyh.treeSet.Student cannot be cast to
// java.lang.Comparable
for (Student2 s : ts) {
System.out.println(s.getName() + "---" + s.getAge());
} }

      b: 比较器排序(集合具备比较性)

        让集合构造方法接收Comparator的实现类对象(但是我们一般用匿名内部类的方式实现)

方式1、我们不用内部类的方式实现:

定义一个类实现Comparator<T> 接口,重写compare方法:

 package com.wyh.treeSet2;

 import java.util.Comparator;

 /**
* @author WYH
* @version 2019年11月17日 下午2:48:22
*/
public class MyComparator implements Comparator<Student2> { @Override
public int compare(Student2 s1, Student2 s2) {
int num = s1.getName().length() - s2.getName().length();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
return num3;
} }

测试类:

 package com.wyh.treeSet2;

 import java.util.Comparator;
import java.util.TreeSet; /**
* @author WYH
* @version 2019年11月17日 下午2:27:13
*
* 根据年龄的长度进行排序
*/
public class TreeSetDemo03 {
public static void main(String[] args) {
// TreeSet<Student2> ts = new TreeSet<Student2>();
TreeSet<Student2> ts = new TreeSet<Student2>(new MyComparator()); //如果一个方法的参数是接口,那么真正要的是实现这个接口的实现类
//匿名内部类可以是实现
/* TreeSet<Student2> ts = new TreeSet<Student2>(new Comparator<Student2>(){
@Override
public int compare(Student2 s1, Student2 s2) {
int num = s1.getName().length() - s2.getName().length();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
return num3;
}
});*/ // 创建学生对象
Student2 s1 = new Student2("王友虎", 22);
Student2 s2 = new Student2("赵以浩", 24);
Student2 s3 = new Student2("齐博源", 21);
Student2 s4 = new Student2("李先锋", 23);
Student2 s5 = new Student2("李宏灿", 22);
Student2 s6 = new Student2("薛长城", 23);
Student2 s7 = new Student2("黄天祥", 24);
Student2 s8 = new Student2("王友虎", 23); // 添加到TreeSet中
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
ts.add(s8); // 遍历
// 如果不重写自然排序方法,就会报错,因为没有给定如何排序,也没有保证唯一性
// java.lang.ClassCastException: com.wyh.treeSet.Student cannot be cast to
// java.lang.Comparable
for (Student2 s : ts) {
System.out.println(s.getName() + "---" + s.getAge());
} } }

方式2、用匿名内部类的方式实现:

 package com.wyh.treeSet2;

 import java.util.Comparator;
import java.util.TreeSet; /**
* @author WYH
* @version 2019年11月17日 下午2:27:13
*
* 根据年龄的长度进行排序
*/
public class TreeSetDemo03 {
public static void main(String[] args) {
// TreeSet<Student2> ts = new TreeSet<Student2>();
// TreeSet<Student2> ts = new TreeSet<Student2>(new MyComparator()); //如果一个方法的参数是接口,那么真正要的是实现这个接口的实现类
//匿名内部类可以是实现
TreeSet<Student2> ts = new TreeSet<Student2>(new Comparator<Student2>(){
@Override
public int compare(Student2 s1, Student2 s2) {
int num = s1.getName().length() - s2.getName().length();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
return num3;
}
}); // 创建学生对象
Student2 s1 = new Student2("王友虎", 22);
Student2 s2 = new Student2("赵以浩", 24);
Student2 s3 = new Student2("齐博源", 21);
Student2 s4 = new Student2("李先锋", 23);
Student2 s5 = new Student2("李宏灿", 22);
Student2 s6 = new Student2("薛长城", 23);
Student2 s7 = new Student2("黄天祥", 24);
Student2 s8 = new Student2("王友虎", 23); // 添加到TreeSet中
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
ts.add(s8); // 遍历
// 如果不重写自然排序方法,就会报错,因为没有给定如何排序,也没有保证唯一性
// java.lang.ClassCastException: com.wyh.treeSet.Student cannot be cast to
// java.lang.Comparable
for (Student2 s : ts) {
System.out.println(s.getName() + "---" + s.getAge());
} } }

  (4)案例:

    A: 获取无重复的随机数(HashSet实现)

 package com.wyh.HashSet_random;

 import java.util.Arrays;
import java.util.HashSet;
import java.util.Random; /**
* @author WYH
* @version 2019年11月17日 下午3:14:10
*
* 实现10个1-20的随机数
*
*
*
*/
public class HashSet_random_Demo {
public static void main(String[] args) {
//创建随机数对象
Random r = new Random(); //创建HashSet集合
HashSet<Integer> hs = new HashSet<Integer>(); //判断元素是否小于10
while(hs.size()<10) {
int num = r.nextInt(20)+1;
hs.add(num);
} Object[] obj = hs.toArray();
Arrays.sort(obj); //遍历集合
for(Object i : obj) {
System.out.println(i);
}
}
}

    B: 键盘录入学生按照总分从搞到底输出(TreeSet且用匿名内部类实现)

 package TreeSet_Scanner;

 import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet; /**
* @author WYH
* @version 2019年11月17日 下午3:25:25
*
* 键盘录入5个学生信息,并且按照总分高低排序
*/
public class TreeSetDemo {
public static void main(String[] args) {
//创建控制台输入对象
Scanner sc = new Scanner(System.in); TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){
@Override
public int compare(Student s1, Student s2) {
/*int num = s1.getName().length() - s2.getName().length();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
int num3 = num2 == 0 ? s1.getSum() - s2.getSum() : num2;
return num3;*/
int num = s2.getSum() - s1.getSum();
int num2 = num == 0 ? s1.getMathNum() - s2.getMathNum() : num;
int num3 = num2 == 0 ? s1.getChinaNum() - s2.getChinaNum() : num2;
int num4 = num3 == 0 ? s1.getEngnishNum() - s2.getEngnishNum() : num3;
int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName()) : num4;
return num5;
}
}); System.err.println("录入开始:");
for(int i = 0 ; i < 5 ; i++) {
Student s = new Student();
System.out.print("请输入第"+(i+1)+"个学生的姓名:");
String name = sc.next();
s.setName(name);
System.out.print("请输入该学生的数学成绩:");
int mNum = sc.nextInt();
s.setMathNum(mNum);
System.out.print("请输入该学生的语文成绩:");
int cNum = sc.nextInt();
s.setChinaNum(cNum);
System.out.print("请输入该学生的英语成绩:");
int eNum = sc.nextInt();
s.setEngnishNum(eNum); int sum = mNum + cNum + eNum;
s.setSum(sum); ts.add(s);
System.out.println();
}
System.err.println("录入结束!"); System.out.println("姓名\t数学成绩\t语文成绩\t英语成绩\t总分");
for(Student s : ts) {
System.out.println(s.getName()+"\t"+s.getMathNum()+"\t"+s.getChinaNum()+"\t"+s.getEngnishNum()
+"\t"+s.getSum());
} } }

2、Collection 集合体系 总结:

我们学完了Set集合,这个Collection体系下的另一个大模块,我们再来总结一下,把漏的LinkedList也总结一下:

  Collection

    | - - List 有序,可重复

      | - - ArrayList

          底层数据结构是数组,查询快,增删慢。

          线程不安全,效率高。

      | - - Vector

          底层数据结构是数组,查询快,增删慢。

          线程安全,效率低。

      | - - LinkedList

          底层数据结构是链表,查询慢,增删快。

          线程不安全,效率高。

    | - - Set 无序,唯一

      | - - HashSet

          底层数据结构是哈希表。

          如何保证元素唯一性的呢?

            依赖两个方法:hashCode()和equals()方法

            开发中自动生成这两个方法即可。

          | - - LinkedHashSet

            底层数据结构是链表和哈希表

            由链表保证元素有序

            由哈希表保证元素唯一

人的类:重写方法

 package com.wyh.linkedHashSet;

 /**
* @author WYH
* @version 2019年11月17日 上午9:21:02
*/
public class Person {
private String name;
private int age; public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
} 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;
Person other = (Person) 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;
} }

测试类:

 package com.wyh.linkedHashSet;

 import java.util.LinkedHashSet;

 /**
* @author WYH
* @version 2019年11月17日 上午9:40:25
*
* LinkedHashSet: 底层是由哈希表和链表实现的
*
* 哈希表确保元素的唯一性
* 链表确保元素有序(存储和取出一致 )
*/
public class LinkedHashSetDemo1 {
public static void main(String[] args) {
LinkedHashSet<Person> lhs = new LinkedHashSet<Person>();
//创建Person类
Person p1 = new Person("小虎",22);
Person p2 = new Person("小强",23);
Person p3 = new Person("小虎",22);
Person p4 = new Person("小美",21);
Person p5 = new Person("小雪",21); lhs.add(p1);
lhs.add(p2);
lhs.add(p3);
lhs.add(p4);
lhs.add(p5); //
for(Person p : lhs) {
System.out.println(p.getName()+"---"+p.getAge());
} } }

      | - - TreeSet

          底层数据结构是红黑树。

          如何保证元素的排序的呢?

            自然排序

            比较器排序

          如何保证元素唯一性呢?

            根据比较的返回值是否是0来决定

3、针对Collection集合我们到底使用谁呢?

    唯一吗?

      是:Set

        排序吗?

          是:TreeSet

          否:HashSet

      如果知道是Set,但是不知道是哪个Set,就用HashSet。

      否:List

        要安全吗?

          是:vector

          否:ArrayList 或者 LinkedList

            查询多:ArrayList

            增删多:LinkedList

      如果知道是List,但是不知道是哪个List,就用ArrayList。

    如果知道使用Collection集合,但是不知道使用谁,就用ArrayList。

  如果知道是用集合,就用ArrayList.

4、在集合中常见的数据结构

  ArrayXxx:底层数据结构是数组,查询快,增删慢。

  LinkedXxx: 底层数据结构是链表,查询慢,增删快。

  HashXxx: 底层数据结构是哈希表,依赖两个方法:hashCode() 和equals()方法

  TreeXxx: 底层数据结构是二叉树,两种方式排序,自然排序和比较器排序。

大数据之路week02 Collection 集合体系收尾(Set)的更多相关文章

  1. 大数据之路week02 List集合的子类

    1:List集合的子类(掌握) (1)List的子类特点 ArrayList: 底层数据结构是数组,查询快,增删慢. 线程不安全,效率高. Vector: 底层数据结构是数组,查询快,增删慢. 线程安 ...

  2. 大数据之路week02--day03 Map集合、Collections工具类的用法

    1.Map(掌握) (1)将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值. (2)Map和Collection的区别? A: Map 存储的是键值对形式的元素,键唯一,值可以 ...

  3. 黑马基础阶段测试题:创建一个存储字符串的集合list,向list中添加以下字符串:”C++”、”Java”、” Python”、”大数据与云计算”。遍历集合,将长度小于5的字符串从集合中删除,删除成功后,打印集合中的所有元素

    package com.swift; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; ...

  4. 大数据之路week01--自学之集合_1(Collection)

    经过我个人的调查,发现,在今后的大数据道路上,集合.线程.网络编程变得尤为重要,为什么? 因为大数据大数据,我们必然要对数据进行处理,而这些数据往往是以集合形式存放,掌握对集合的操作非常重要. 在学习 ...

  5. 大数据之路week01--day02_2 集合方面的总结

    (初稿 太晚了,明天再进行补充) 1.对象数组(掌握) (1)数组既可以存储基本数据类型,也可以存储引用类型.它存储引用类型的时候的数组就叫对象数组. (2)案例: 用数组存储5个学生对象,并遍历数组 ...

  6. 胖子哥的大数据之路(9)-数据仓库金融行业数据逻辑模型FS-LDM

    引言: 大数据不是海市蜃楼,万丈高楼平地起只是意淫,大数据发展还要从点滴做起,基于大数据构建国家级.行业级数据中心的项目会越来越多,大数据只是技术,而非解决方案,同样面临数据组织模式,数据逻辑模式的问 ...

  7. 胖子哥的大数据之路(6)- NoSQL生态圈全景介绍

    引言: NoSQL高级培训课程的基础理论篇的部分课件,是从一本英文原著中做的摘选,中文部分参考自互联网.给大家分享. 正文:  The NoSQL Ecosystem 目录 The NoSQL Eco ...

  8. 大数据之路week04--day06(I/O流阶段一 之异常)

    从这节开始,进入对I/O流的系统学习,I/O流在往后大数据的学习道路上尤为重要!!!极为重要,必须要提起重视,它与集合,多线程,网络编程,可以说在往后学习或者是工作上,起到一个基石的作用,没了地基,房 ...

  9. C#码农的大数据之路 - 使用C#编写MR作业

    系列目录 写在前面 从Hadoop出现至今,大数据几乎就是Java平台专属一般.虽然Hadoop或Spark也提供了接口可以与其他语言一起使用,但作为基于JVM运行的框架,Java系语言有着天生优势. ...

随机推荐

  1. Vue.js—60分钟快速入门

    本文摘自:http://www.cnblogs.com/keepfool/p/5619070.html Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的 ...

  2. php 获取文件mime类型的方法

    php 获取文件mime类型的方法 使用fileinfo需要安装php_fileinfo扩展. 如已安装可以在extension_dir目录下找到php_fileinfo.dll(windows),f ...

  3. 暴力解决HTMLTestRunner出现dict() ->new empty dictionary的问题

    在使用ddt数据驱动之后,HTMLTestRunner报告的用例名称之后出现dict() ->new empty dictionary,如下图所示: 经排查,发现是因为ddt源码中test_do ...

  4. 解决maven项目无法读取src/main/java目录下面的配置文件问题

    我们在用Mybatis去操作底层数据库的时候,需要用到xml配置文件,一般我们是把配置文件和dao放置在同一层目录. 但是在用idea操作maven项目的时候,我们可能会遇到无法读取到dao对应的ma ...

  5. VMware的下载与安装

    VMware的下载与安装 一.虚拟机的下载 1.进入VMware官网,点击左侧导航栏中的下载,再点击图中标记的Workstation Pro,如下图所示. 2.根据操作系统选择合适的产品,在这里以Wi ...

  6. WUST Oracle数据库 实验一实验二

    链接:https://pan.baidu.com/s/1hCzvTLzXhyItP2gD_69gzg 提取码:j68f 复制这段内容后打开百度网盘手机App,操作更方便哦

  7. Vue CLI 3开发中屏蔽的EsLint错误 (.eslintrc.js 在vue3+中 修改这个)

    1.关闭eslint校验有了eslint的校验,可以来规范开发人员的代码,是挺好的.但是有些像缩进.空格.空白行之类的规范,在开发过程中一直报错,未免太过于苛刻了.所以,我还是会选择关闭eslint校 ...

  8. 一文搞懂嵌入式uboot、kernel、文件系统的关系

    总览: 在linux系统软件架构可以分为4个层次(从低到高分别为):   1.引导加载程序         引导加载程序(Bootloader)是固化在硬件Flash中的一段引导代码,用于完成硬件的一 ...

  9. CMake入门-03-还是HelloWorld

    工作环境 系统:macOS Mojave 10.14.6 CMake: Version 3.15.0-rc4 Hello,World! 扩展-math 目录里的文件编译成静态库再由 main 函数调用 ...

  10. (八)CXF之用spring添加拦截器

    一.案例 本章案例是基于CXF之自定义拦截器基础之上改造的,目的是在服务端中用spring添加拦截器 配置web.xml <?xml version="1.0" encodi ...