1、集合-HashSet:存储不重复的元素,没有索引
底层主要是调用HashCode和Equals方法判断
存储字符:
HashSet<String> hs = new HashSet<>();
boolean b1 = hs.add("a");
boolean b2 = hs.add("a"); //当存储不成功的时候,返回false
System.out.println(b1);
System.out.println(b2);
for(String s : hs) {
System.out.println(s); //输出[a]
}
2、集合-HashSet存储自定义对象
HashSet<Person> hs = new HashSet<>();
hs.add(new Person("张三", 23));
hs.add(new Person("张三", 23));
hs.add(new Person("李四", 24));
//System.out.println(hs.size());
System.out.println(hs); //实际上没有把重复的删除
因为需要调用对象的HashCode和Equals的方法,但是Person类中没有重写
例如:
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
/*
* 为什么是31?
* 1,31是一个质数,质数是能被1和自己本身整除的数
* 2,31这个数既不大也不小
* 3,31这个数好算,2的五次方-1,2向左移动5位
*/
@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;
}
//可以使用eclipse自动生成equals方法
@Override
public boolean equals(Object obj) {
if (this == obj) //调用的对象和传入的对象是同一个对象
return true; //直接返回true
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; //返回false
return true; //返回true
}
}
3、集合-HashSet原理
我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
如果没有哈希值相同的对象就直接存入集合
如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
4、集合-LinkedHashSet:可以保证怎么存就怎么取
底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
LinkedHashSet<String> lhs = new LinkedHashSet<>();
lhs.add("a");
lhs.add("a");
lhs.add("a");
lhs.add("a");
lhs.add("b");
lhs.add("c");
lhs.add("d");
System.out.println(lhs);
//输出的是[a,b,c,d]
5、集合-TreeSet:可以进行排序
TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
底层是根据compareTo()方法返回的结果进行存储
如果需要排序自定义的类,就需要重写里面的compareTo方法
例如:
TreeSet<Integer> ts = new TreeSet<>();
ts.add(3);
ts.add(1);
ts.add(1);
ts.add(2);
ts.add(2);
ts.add(3);
ts.add(3);
System.out.println(ts);
//返回的是[1,2,3]
6、集合-TreeSet原理:
当compareTo方法返回0的时候集合中只有一个元素,就不存储
当compareTo方法返回负数的时候集合会倒序存储,就存在树的左边
当compareTo方法返回正数的时候集合会怎么存就怎么取,就存在树的右边
取数据的时候就从最左边开始取(从根开始,如果左边有数据就看这个数据的左边还有没有,依次类推,到了最左边就取出来)
TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
TreeSet如果传入Comparator, 就优先按照Comparator
例如:
public static void main(String[] args) {
//需求:将字符串按照长度排序
TreeSet<String> ts = new TreeSet<>(new CompareByLen()); //Comparator c = new CompareByLen();
ts.add("aaaaaaaa");
ts.add("z");
ts.add("wc");
ts.add("nba");
ts.add("cba");
System.out.println(ts);
}
//定义一个比较器的类,实现Comparator接口
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; //内容为次要条件,s1就是"z"需要比较的字符串(ts.add("z");),s2就是TreeSet里面的数据
} //==0就按默认的排序
}
底层主要是调用HashCode和Equals方法判断
存储字符:
HashSet<String> hs = new HashSet<>();
boolean b1 = hs.add("a");
boolean b2 = hs.add("a"); //当存储不成功的时候,返回false
System.out.println(b1);
System.out.println(b2);
for(String s : hs) {
System.out.println(s); //输出[a]
}
2、集合-HashSet存储自定义对象
HashSet<Person> hs = new HashSet<>();
hs.add(new Person("张三", 23));
hs.add(new Person("张三", 23));
hs.add(new Person("李四", 24));
//System.out.println(hs.size());
System.out.println(hs); //实际上没有把重复的删除
因为需要调用对象的HashCode和Equals的方法,但是Person类中没有重写
例如:
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
/*
* 为什么是31?
* 1,31是一个质数,质数是能被1和自己本身整除的数
* 2,31这个数既不大也不小
* 3,31这个数好算,2的五次方-1,2向左移动5位
*/
@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;
}
//可以使用eclipse自动生成equals方法
@Override
public boolean equals(Object obj) {
if (this == obj) //调用的对象和传入的对象是同一个对象
return true; //直接返回true
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; //返回false
return true; //返回true
}
}
3、集合-HashSet原理
我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
如果没有哈希值相同的对象就直接存入集合
如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
4、集合-LinkedHashSet:可以保证怎么存就怎么取
底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
LinkedHashSet<String> lhs = new LinkedHashSet<>();
lhs.add("a");
lhs.add("a");
lhs.add("a");
lhs.add("a");
lhs.add("b");
lhs.add("c");
lhs.add("d");
System.out.println(lhs);
//输出的是[a,b,c,d]
5、集合-TreeSet:可以进行排序
TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
底层是根据compareTo()方法返回的结果进行存储
如果需要排序自定义的类,就需要重写里面的compareTo方法
例如:
TreeSet<Integer> ts = new TreeSet<>();
ts.add(3);
ts.add(1);
ts.add(1);
ts.add(2);
ts.add(2);
ts.add(3);
ts.add(3);
System.out.println(ts);
//返回的是[1,2,3]
6、集合-TreeSet原理:
当compareTo方法返回0的时候集合中只有一个元素,就不存储
当compareTo方法返回负数的时候集合会倒序存储,就存在树的左边
当compareTo方法返回正数的时候集合会怎么存就怎么取,就存在树的右边
取数据的时候就从最左边开始取(从根开始,如果左边有数据就看这个数据的左边还有没有,依次类推,到了最左边就取出来)
TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
TreeSet如果传入Comparator, 就优先按照Comparator
例如:
public static void main(String[] args) {
//需求:将字符串按照长度排序
TreeSet<String> ts = new TreeSet<>(new CompareByLen()); //Comparator c = new CompareByLen();
ts.add("aaaaaaaa");
ts.add("z");
ts.add("wc");
ts.add("nba");
ts.add("cba");
System.out.println(ts);
}
//定义一个比较器的类,实现Comparator接口
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; //内容为次要条件,s1就是"z"需要比较的字符串(ts.add("z");),s2就是TreeSet里面的数据
} //==0就按默认的排序
}