Hashset集合
存储字符串并遍历

import java.util.HashSet;
public class dmo1_hashset {
//set集合,无索引,不可以重复,无序(存取不一致)
public static void main(String[] args) {
HashSet<String> hSet=new HashSet<>(); //创建hashset对象
boolean b1=hSet.add("a");
boolean b2=hSet.add("a"); //当向set集合中存储重复元素的时候返回为false
hSet.add("b");
hSet.add("c");
hSet.add("d");
System.out.println(hSet); //hashset的继承体系中有重写toString方法
//System.out.println(b1);
//System.out.println(b2);
for (String string : hSet) { //只要能用迭代器迭代的,就可以使用增强for循环遍历
System.out.println(string);
}
}
}
存储自定义对象保证元素唯一性
Hashset原理
我们使用set集合都是需要去掉重复元素的,如果在存储的时候逐个equals()比较,效率较低,哈希算法提高了重复的效率,降低了使用equals()方法的次数
当Hashset调用add()方法存储对象的时候,先调用对象的hashset()方法得到一个哈希值,然后在集合中查找是否有哈希值相同的对象:
如果没有哈希值相同的对象就直接存入集合
如果有哈希值相同的对象,就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入,true则不存
将自定义累的对象存入Hashset去重复
类中必须重写hashCode()和equals()方法
hashCode():属性相同的对象返回值此项相同,属性不同的返回值尽量不同(提高效率)
equals():属性相同返回true,属性不同返回false,返回false的时候存储
import java.util.HashSet;
import tan.jung.bean.Person;
public class demo2_hashset {
public static void main(String[] args) {
HashSet<Person> hs =new HashSet<>();
hs.add(new Person("张三",23));
hs.add(new Person("张三",23));
hs.add(new Person("张三",23));
hs.add(new Person("李四",24));
hs.add(new Person("李四",24));
System.out.println(hs); //需要重写equals和HashCode方法
}
}
//第二个包
public class Person {
private String name;
private int 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;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
/*@Override
public boolean equals(Object obj) {
System.out.println("执行了");
Person p=(Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
@Override
public int hashCode() {
final int num=38;
return name.hashCode() * num +age;
}*/
@Override
public int hashCode() {
final int prime = 31; //31是一个质数,质数是能被1和自己本身整除的数 ,即不大也不小,比较好算,2的五次方-1,2向左移动五位
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; //直接返回rute
if (obj == null) //传入的对象为null
return false; //返回false
if (getClass() != obj.getClass()) //判断两个对象对应的字节码未见是否是同一个字节码
return false; //如果不是直接返回false
Person other = (Person) obj; //向下转型
if (age != other.age) //调用对象的年内不等于传入对象的年龄
return false; //返回false
if (name == null) { //调用对象的姓名不为null
if (other.name != null) //传入对象的姓名不为null
return false; //返回false
} else if (!name.equals(other.name)) //调用对象的姓名不等于传入对象的姓名
return false; //返回flase
return true; //返回true
}
}
LinkedHashset
特点:
可以保证怎么存就怎么取
底层是连带实现的,是set集合中唯一一个能保证怎么存怎么取得集合对象
因为Hashset的子类,所以也是保证元素唯一的,与Hashset的原理一样
随机数

public class test1 {
public static void main(String[] args) {
//创建Random类创建随机数对象
Random r1=new Random();
//不能重复,需要用Hashset方法
HashSet<Integer> hs1=new HashSet<>();
//hashset的size是下雨10就可以不断存储,如果大于等于10就停止存储
while (hs1.size()<10) {
//通过random类中的nextInt(n)方法获取1到20之间的随机数,并将这些随机数存现在hashset集合中
hs1.add(r1.nextInt(21));
}
//遍历Hashset
for (Integer integer : hs1) {
System.out.println(integer);
}
}
键盘输入,去掉重复

import java.util.HashSet;
import java.util.Scanner;
import javax.sound.sampled.Line;
public class test2 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入");
//创建Hashset独享,将字符存储,去掉重复
HashSet<Character> hs1 =new HashSet<>();
//将字符串转换成字符数组,获取每一个字符存储在Hashset集合中,自动去除重复
String line=sc.nextLine();
char[] arr=line.toCharArray();
for (char c : arr) { //遍历字符数组
hs1.add(c);
}
//遍历Hashset,打印每一个字符
for(Character ch:hs1){
System.out.println(ch);
}
}
}
去除集合中的重复

import java.util.ArrayList;
import java.util.LinkedHashSet;
public class test3 {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
list.add("a");
list.add("a");
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
getSingle(list); //调用方法
System.out.println(list);
}
public static void getSingle(ArrayList<String> list) {
LinkedHashSet<String> lsh=new LinkedHashSet<>();
lsh.addAll(list); //添加list元素
list.clear(); //清除list元素
list.addAll(lsh); //将LinkedHashset集合中的元素添加会list集合中
}
}
TreeSet
Treeset存储Integer类型的元素并遍历

import java.util.TreeSet;
public class demo4_TreeSet {
//TreeSet集合是用来对对象元素进行排序的,同事也可以保证元素的唯一
public static void main(String[] args) {
TreeSet<Integer> ts1=new TreeSet<>();
ts1.add(1);
ts1.add(1);
ts1.add(2);
ts1.add(2);
ts1.add(3);
ts1.add(3);
ts1.add(3);
ts1.add(4);
ts1.add(4);
System.out.println(ts1);
}
}
TreeSet存储自定义对象
二叉数:两个叉
小的存储在左边(负数),打的存储在右边(整数),相等就不存(0)
compareTo方法,在TreeSet集合如何存储元素取决于compareTo方法的返回值
返回0,集合中只有一个元素
返回负数集合会将存储的元素倒序
返回整数会怎么存怎么取

import java.util.Iterator;
import java.util.TreeSet;
import tan.jung.bean.Person;
/*当compareTo方法返回0的时候集合中只有一个元素
*当compareTo方法返回整数的时候集合会怎么存就怎么取
*当compareTo方法返回负数的时候集合会倒序存储
* */
public class demo5_TreeSet {
public static void main (String args[]){
TreeSet<Person> ts1=new TreeSet<>();
ts1.add(new Person("xx",20));
ts1.add(new Person("hh",20));
ts1.add(new Person("nn",20));
ts1.add(new Person("mm",20));
Iterator<Person> it1=ts1.iterator();
while (it1.hasNext()) {
Person p1=it1.next();
System.out.println(p1.getName()+" "+p1.getAge());
}
//System.out.println(ts1);
}
}
//第二个包
public class Person implements Comparable<Person>{
private String name;
private int 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;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
/*@Override
public boolean equals(Object obj) {
System.out.println("执行了");
Person p=(Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
@Override
public int hashCode() {
final int num=38;
return name.hashCode() * num +age;
}*/
@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;
}
@Override
public int compareTo(Person o) {
return -1;
}
}
按照姓名排序
按照年龄排序

import java.util.Iterator;
import java.util.TreeSet;
import tan.jung.bean.Person;
/*当compareTo方法返回0的时候集合中只有一个元素
*当compareTo方法返回整数的时候集合会怎么存就怎么取
*当compareTo方法返回负数的时候集合会倒序存储
* */
public class demo5_TreeSet {
public static void main (String args[]){
//demo1();
TreeSet<Person> ts1=new TreeSet<>();
ts1.add(new Person("张三",20));
ts1.add(new Person("李四",12));
ts1.add(new Person("王五",25));
ts1.add(new Person("赵六",11));
ts1.add(new Person("七七",11));
System.out.println('张'+0);
System.out.println('李'+0);
System.out.println('王'+0);
System.out.println('赵'+0);
System.out.println('七'+0);
Iterator<Person> it1=ts1.iterator();
while (it1.hasNext()) {
Person p1=it1.next();
System.out.println(p1.getName()+" "+p1.getAge());
}
}
public static void demo1() {
TreeSet<Person> ts1=new TreeSet<>();
ts1.add(new Person("xx",20));
ts1.add(new Person("hh",12));
ts1.add(new Person("nn",25));
ts1.add(new Person("mm",11));
ts1.add(new Person("ss",11));
Iterator<Person> it1=ts1.iterator();
while (it1.hasNext()) {
Person p1=it1.next();
System.out.println(p1.getName()+" "+p1.getAge());
}
}
}
//第二个包
import java.awt.RenderingHints;
public class Person implements Comparable<Person>{
private String name;
private int 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;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
/*@Override
public boolean equals(Object obj) {
System.out.println("执行了");
Person p=(Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
@Override
public int hashCode() {
final int num=38;
return name.hashCode() * num +age;
}*/
@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;
}
/*@Override
public int compareTo(Person o) {
int num =this.age-o.age; //年龄是主要条件
return num==0 ? this.name.compareTo(o.name) : num;
}*/
@Override
public int compareTo(Person o) {
int num=this.name.compareTo(o.name);
int num2=this.age-o.age;//姓名是主要条件
return num==0 ? num2 :num;
}
}
按照姓名长度排序

public int compareTo(Person o) {
int length =this.name.length() - o.name.length(); //比较长度为主要条件
int num =length == 0? this.name.compareTo(o.name) :length;//比较内容为次要条件
//如果length等于0的话就比较this.name.compareTo(o.name) ,compare比较内容
//如果不等于0的话就比较length
return num ==0 ? this.age-o.age :num; //比较年龄为次要条件
}
接口不能直接new 需要给子类对象

public class demo5_TreeSet {
public static void main (String args[]){
//demo1();
//demo2();
//demo3();
TreeSet<String> ts1=new TreeSet<>(new CompareByLen());
//compare c=new CompareByLen();
ts1.add("abccd");
ts1.add("z");
ts1.add("bb");
ts1.add("sss");
System.out.println(ts1);
}
}
class CompareByLen implements Comparator<String>{
@Override
public int compare(String s1, String s2) { //按照字符串的长度比较
int num =s1.length() -s2.length(); //长度为主要条件
return num == 0 ?s1.compareTo(s2) : num ; //内容为次要条件
}
}
TreeSet原理
特点:
TreeSet是用来排序的,可以指定一个顺序,对象存入之后会按照指定的顺序排列
使用方式:
1.自然排序(Comparable)
TreeSet类的add()方法中会把存入的对象提升为Comparable类型
调用对象的compareTo()方法和集合中的对象比较
根据compareTo()方法返回结果进行存储
2.比较器顺序(Comparator)
创建TreeSet的时候可以制定一个Comparatpr
如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序
add()犯法内部会自动调用Comparator接口中compare()方法排序
调用的对象是compare()方法的第一个参数,集合中的对象是compare方法的第二个参数
3.两种方式区别:
TreeSet构造函数什么都不传,默认按照类中Comparable的顺序(没有就报错ClassCasException)
TreeSet如果传入了Comparator,就优先按照Comparator
来源:https://www.cnblogs.com/JungTan0113/p/10930675.html
