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