Set集合概述以及特点:

  • set 是一个不包含重复元素的collection
  • set只是一个接口,一般使用它的子类HashSet,LinkedHashSet,TreeSet

HashSet

  • 此类是Set接口的实现类,有哈希表支持
  • 它不保证set的迭代顺序,特别是不保证顺序的恒久不变
  • 此类允许使用null元素

我们一般使用HashSet来去重:

  • 我们需要重写累的hashCode()和equals()方法

HashSet去重的依据:

  首先会比较hashCode(),如果不一样则存进去,如果一样的话,调用equals()方法进行比较,如果返回True就不存储,false存储

面试题:为什么自动生成hashCode的时候有个31的数?

31是一个质数,质数是能被1和自己本身整除的数,没有公约数

31刚刚好,既不大也不小

31这个数好算,2的五次方-1,相当于向左移5位-1

答案

案例:产生10个1-20之间的随机数要求随机数不能重复

package l1;

import java.util.HashSet;
import java.util.Random;
import java.util.Set; public class Demo01 { public static void main(String[] args) {
// TODO Auto-generated method stub Set<Integer> set = new HashSet<Integer>();
Random rd = new Random();
while(set.size()!=10){
int r = rd.nextInt(21); //生成1-20之间的随机数
if(r!=0){
set.add(r);
}
}
System.out.println(set); } }

案例:从键盘读取一行输入,去掉重复字符并打印

package l2;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set; public class Demo2 { public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一行内容");
String line = sc.nextLine(); //将字符串转化为字符数组
char[] ch = line.toCharArray(); Set<Character> set = new HashSet<Character>();
for(char a:ch){
set.add(a);
} System.out.println(set);
} }

案例:使用HashSet()过滤List集合中的重复的元素

package l3;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set; public class Demo3 { public static void main(String[] args) {
List<String> li = new ArrayList<String>();
li.add("A");
li.add("B");
li.add("A");
li.add("A");
Set<String> set = new HashSet<String>();
set.addAll(li);
System.out.println(set); } }

LinkedHashSet的概述和使用

  • LinkedHashSet是一个具有可预知迭代顺序的Set接口
  • 内部实现是使用哈希表和链接列表
  • LinkedHashSet的特点是可以保证怎么存就怎么取
  • LinkedHashSet是set集合中唯一一个能保证怎么存就怎么取的集合对象
  • LinkedHashSet是HashSet的子类,所以也是保证元素唯一的,实现原理和HashSet一样

TreeSet的概述和使用

  • TreeSet是一个可以用于排序的集合、
  • TreeSet给予TreeMap的NavigableSet实现
  • TreeSet的排序方法有两种:
    • 使用元素的自然顺序Comparable对元素进行排序
    • 使用构造方法的Comparator进行排序

使用TreeSet 存储自定义对象:

注意:使用TreeSet存储自定义对象是会出现异常:xxxx cannot be cast to java.lang.Comparable

  • 如果想用TreeSet存储自定义对象,这个对象必须要实现Comparable接口
  • 此接口强行堆实现它的每个类的对象进行排序
  • 这种排序被称为自然排序,类的compareTo方法被成为它的自然比较方法
  • 当compareTo方法返回0的时候,集合只会保留一个元素
  • 当compareTo方法返回正数的时候,集合怎么存就怎么取
  • 当compareTo方法返回负数的时候,集合会倒序存储

TreeSet存储自定义对象并遍历

package lesson0001;

import java.util.Set;
import java.util.TreeSet; public class Demo1 { public static void main(String[] args) { Set<Student> set = new TreeSet<Student>();
set.add(new Student(1,"n1"));
set.add(new Student(2,"n2"));
set.add(new Student(3,"n3"));
for(Student std:set){
System.out.println(std);
}
} } class Student implements Comparable{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public int compareTo(Object arg0) {
return 1;
}
}

以上是最简单的一个例子,然后呢,我们现在需要实现:

  TreeSet存储自定义对象并且遍历,而且要按照姓名长度,字母,年龄顺序排序

  • 通过比较字符串的compareTo比较大小
  • 排序按照unicode码的大小进行排序
  • 防止名字相同,但年龄不同的Bug
package lesson0002;

import java.util.Set;
import java.util.TreeSet; public class Demo1 { public static void main(String[] args) { Set<Student> set = new TreeSet<Student>();
set.add(new Student(1,"aaaa"));
set.add(new Student(5,"aaaa"));
set.add(new Student(2,"aaaa"));
set.add(new Student(1,"aaa"));
set.add(new Student(1,"aa"));
for(Student std:set){
System.out.println(std);
} } }

main代码

package lesson0002;

public class Student implements Comparable<Student> {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
@Override
public int compareTo(Student o) {
int length = this.name.length() - o.name.length();
int num = length == 0?this.name.compareTo(o.name):length;
return num == 0?this.age-o.age:num;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
} }

Student类

TreeSet除了这种自定义排序意外还可以定义一种自定义排序:比较器(Comparator)

package lesson0003;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet; //比较器排序 public class Demo1 { public static void main(String[] args) { Set<String> set = new TreeSet<String>(new Comparator<String>() { @Override
public int compare(String o1, String o2) { int num = o1.compareTo(o2);//默认的从小到大
num = num==0?1:num; //如果相同返回1,即保存同名的元素
return num;
}
}); set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("aaa");
set.add("aa");
for(String s:set){
System.out.println(s);
}
} }

TreeSet的总结

TreeSet是用来排序的,可以指定一个顺序,对象存入之后会按照指定的顺序排序

TreeSet的排序方式有两种:

  • 自然排序
  • 比较器顺序

自然顺序:

  1. TreeSet类的add方法会把存入的对象提升为Comparable类型
  2. 调用对象的compareTo方法进行比较
  3. 根据compareTo方法返回的结果进行一个存储

比较器顺序:

  1. 创建TreeSet的时候可以定制一个Comparator
  2. 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器的规则比较
  3. add方法内部会调用Comparator接口中的compare方法排序
  4. 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数

自然排序和比较器排序的区别:

  • TreeSet构造函数什么都不传,默认按照类中的Comparable的排序
  • TreeSet如果传入Comparator,就优先按照Comparator(即,比较器排序要优先)

练习题案例:

1.在一个集合中存储了无序并且重复的字符串,让其有序,而且不能去除重复

我上面例子中,比较器排序的那个例子就是

答案

2.从键盘输入多个整数,直到输入quit时结束输入。把所有输入的整数倒叙排列打印

package lesson0004;

import java.util.Comparator;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet; public class Demo01 { public static void main(String[] args) { Set<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() { @Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return (o2-o1)==0?1:(o2-o1);
// return o2-o1;
}
}); Scanner sc = new Scanner(System.in);
while(true){
String str = sc.nextLine();
if("quit".equals(str)){
break;
}else{
set.add(Integer.parseInt(str));
}
}
for(Integer i:set){
System.out.println(i);
} } }

答案

3.键盘录入学生信息按照总分排序后输出在控制台

package lesson0005;

import java.util.Comparator;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet; public class Demo1 { public static void main(String[] args) {
// TODO Auto-generated method stub Set<Student> set = new TreeSet<Student>(); Scanner sc = new Scanner(System.in);
while(true){
System.out.println("请按照格式输入学生信息(学生名:年龄:成绩)");
String line = sc.nextLine();
if("quit".equals(line)){
break;
}else{
String name = line.split(":")[0];
int age = Integer.parseInt(line.split(":")[1]);
int score = Integer.parseInt(line.split(":")[2]);
set.add(new Student(name,age,score));
}
}
for(Student std:set){
System.out.println(std);
} } }

答案:main

package lesson0005;

public class Student implements Comparable<Student> {

    private String name;
private int age;
private int score;
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;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
}
public Student() {
super();
}
public Student(String name, int age, int score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
@Override
public int compareTo(Student o) {
int num = o.score - this.score;
num = num==0?this.name.compareTo(o.name):num;
num = num==0?(this.age-o.age):num;
return num==0?1:num;
} }

答案:Student类

Java学习之路(八):Set的更多相关文章

  1. java学习之路之javaSE基础1

    <h2>java学习之路之javaSE基础1</h2> <div> ###01.01_计算机基础知识(计算机概述)(了解)* A:什么是计算机?计算机在生活中的应用 ...

  2. JAVA学习之路与大家分享

    这是我四年以前总结的JAVA学习之路,希望对初学者或想从事JAVA开发的人有帮助. 本人是软件工程专业出身,先后学过C.C++.JAVA.VB.delphi等等开发语言以及网络相关管理技术.哎,好久不 ...

  3. 新篇章之我的java学习之路下

    昨天写下了人生的第一篇博客,今天接着写我的java学习之路有关开发及框架的学习过程. 想要学好java语言,只学习一些java的基本语法对实际开发中的用处还是不大的,所以我们还要掌握一些有关javaW ...

  4. java学习之路之javaSE基础2

    java学习之路之javaSE基础2 所有的代码都是引用他人写的. 1.逻辑运算符 //&,|,^,! //int x = 10; //5 < x < 15 //x > 5 ...

  5. Java学习之路(转)

    Java学习之路(书籍推荐)   一.基础类 1.<Thinking in java>(阅读2遍),入门第一位是建立正确的概念 2.<Core Java>这本书更贴近实践,更多 ...

  6. Java 学习之路 -- day00

    Java 学习之路 -- day00 Typora 快捷键操作 标题:#+空格 2. *斜体* 3. **加粗** 4. **斜体加粗*** 5. ~~删除线~~ 6. > 引用 7. ···分 ...

  7. (转)如何学习Java技术?谈Java学习之路

    51CTO编者注:这篇文章已经是有数年“网龄”的老文,不过在今天看来仍然经典.如何学习Java?本篇文章可以说也是面对编程初学者的一篇指导文章,其中对于如何学习Java的步骤的介绍,很多也适用于开发领 ...

  8. Java学习之路:不走弯路,就是捷径

    1.如何学习程序设计? JAVA是一种平台,也是一种程序设计语言,如何学好程序设计不仅仅适用于JAVA,对C++等其他程序设计语言也一样管用.有编程高手认为,JAVA也好C也好没什么分别,拿来就用.为 ...

  9. java学习之路

    先来说一说我和it之间的不解之缘.准确来说,我接触it是从大二是我买的第一个手机开始的(国产的,展讯平台,能够运行mrp虚拟机),那时候还没有智能手机,或者说还不够普及,总之就是买不起.一次偶然的机会 ...

随机推荐

  1. 程序员面试50题(1)—查找最小的k个元素[算法]

    题目:输入n个整数,输出其中最小的k个.例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4. 分析:这道题最简单的思路莫过于把输入的n个整数排序,这样排在最前面的k个数 ...

  2. trcd_extract_EDCD_new

    # -*- coding:utf-8 -*- import re ''' 适应新版本 ''' year='17A'#用户自定义 ss='./data/'#根目录 filename = ss+'EDCD ...

  3. 配置HDFS HttpFS和WebHDFS

    HDFS支持两种RESTful接口:WebHDFS和HttpFS. WebHDFS默认端口号为50070,HttpFS默认端口号为14000. 默认启动WebHDFS而不会启动HttpFS,而Http ...

  4. Codeforces807 B. T-Shirt Hunt 2017-05-08 23:23 175人阅读 评论(0) 收藏

    B. T-Shirt Hunt time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  5. 集合(一)ArrayList

    前言 这个分类中,将会写写Java中的集合.集合是Java中非常重要而且基础的内容,因为任何数据必不可少的就是该数据是如何存储的,集合的作用就是以一定的方式组织.存储数据.这里写的集合,一部分是比较常 ...

  6. Android-项目所有文件报红色j,状态栏无法Run 'app'

    项目所有文件报红色j,不可用状态 状态栏如下: 无法 Run 'app' 无法 Debug 'app' ........... 以下操作按钮灰色的,无法点击: 解决方案: 只需要:Sync Proje ...

  7. Postgres重置自增长id列(reset sequence)

    简单的两个方法,个人比较喜欢第一个 ①ALTER SEQUENCE seq RESTART WITH 1;② SELECT setval('sequence_name', 0); 参考自http:// ...

  8. Replication--对发布修改的一些小总结

    --==================================================== --在华丽分割线下,是我对肖磊--大菠萝的崇高地敬意和婶婶地感谢,本文乃肖兄表述我执笔而来 ...

  9. 构建NetCore应用框架之实战篇系列

    构建NetCore应用框架之实战篇 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建Net ...

  10. Prism 的 TabControl 导航

    基于Prism 7.1 最近工作中可能会用到TabControl所以作为小菜的我提前预习了一下,结果并没有我想的那么简单,于是乎 各种网上查,本来用wpf的人就不多 prism 的可查的资料就更少的可 ...