1.Set实现类TreeSet(重点)
实现排序的方式
1.自然排序法------存储对象的类实现Comparable接口
2.比较器法 ------带参构造方法传入比较器对象(Comparator)
1.1 验证原理-存储单个属性的对象
class Person implements Comparable<Person>{
String name;
public Person(String name) {
this.name=name;
}
@Override
public String toString() {
return "Person [name=" + name + "]";
}
@Override
public int compareTo(Person o) {
//按自己方式比较,认为姓名相同则确定唯一
//compareTo方法与二叉树原理匹配的>0 ==0 <0--->升序排列
//return this.name.compareTo(o.name);
return o.name.compareTo(this.name); //倒叙排列
//return 0; //如果返回0,只返回一个对象
}
}
public class Test1 {
public static void main(String[] args) {
Set<Person> set = new TreeSet<Person>();
set.add(new Person("zs")); //ClassCastException: Person cannot be cast to Comparable
set.add(new Person("ls"));
set.add(new Person("zs"));
set.add(new Person("ww"));
System.out.println(set);
}
}
1.2 验证原理-存储多个属性的对象
TreeSet存储对象为两个属性:
分析:需要判断两个属性都一致则认为是同一个对象
//自然排序法—存储类型实现Comparable接口
class Student implements Comparable<Student>{
String name;
int age;
public Student(String name, int age) {
this.name=name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
//排序规则:按年龄比较升序,如果年龄相同,则按姓名的降序
/*if(this.age==o.age) { //年龄相同
return o.name.compareTo(this.name); //姓名降序
}else {
return this.age-o.age; //年龄升序
}*/
//排序规则2:先按姓名的升序排,如果姓名相同,则按年龄的降序
if(this.name.equals(o.name)) {
return o.age-this.age; //年龄的降序
}else {
return this.name.compareTo(o.name);
}
}
}
public class Test2 {
public static void main(String[] args) {
Set<Student> set = new TreeSet<>();
set.add(new Student("zs",20));
set.add(new Student("ls",20));
set.add(new Student("zs",18));
set.add(new Student("ls",20));
System.out.println(set);
}
}
1.3 比较器法
//案例:TreeSet存储两个属性的对象,使用比较器方式
class Teacher{
String name;
int age;
public Teacher(String name,int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Teacher [name=" + name + ", age=" + age + "]";
}
}
public class Test3 {
public static void main(String[] args) {
Set<Teacher> set = new TreeSet<Teacher>(new Comparator<Teacher>() {
@Override
public int compare(Teacher o1, Teacher o2) {
//规则: 先按姓名降序排列,如果姓名相同,在按年龄升序排列
if(o1.name.equals(o2.name)) {
return o1.age-o2.age;
}else {
return o2.name.compareTo(o1.name);
}
}
});
set.add(new Teacher("zs", 13));
set.add(new Teacher("ls", 13));
set.add(new Teacher("zs", 13));
set.add(new Teacher("ls", 15));
System.out.println(set);
}
}
2.TreeMap集合(重点)
2.1 基本使用
Map接口:下面的实现类都实现了存储键值对的特点
存储特点: key无序,且唯一;value允许重复; 如果key重复,那么value会覆盖之前的
Map的实现类HashMap: 通过hash算法实现存储
通过源码分析可知:具体实现与HashSet一致的,因为HashSet就是通过HashMap完成的存储
public class Test1 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("bb", 11);
map.put("aa", 11);
map.put("bb", 22);
//常用方法:
System.out.println(map.get("aa")); //11
System.out.println(map.containsKey("bb")); //true
System.out.println(map.containsValue(22)); //true
Collection<Integer> coll = map.values(); //把所有value放到集合中
System.out.println(coll);
System.out.println(map);
System.out.println(map.size()); //长度2
//----遍历:无下标不能使用基本for-----
//for(int i=0;i<map.size();i++) {}
//Map集合进行遍历的是两个值,不能直接使用增强for遍历
//for(Object o:map) {}
//-------间接遍历: keySet--------
Set<String> keys = map.keySet();
for(String key:keys) {
System.out.println(key+"-->"+map.get(key));
}
//-------间接遍历: entrySet--------
Set <Entry<String, Integer>> set = map.entrySet();
for(Entry<String, Integer> entry:set) {
System.out.println(entry.getKey()+"==>"+entry.getValue());
}
}
}
2.2 HashMap存储自定义对象
hashMap存储自定义对象,验证存储原理
注意:后续的map存储的key往往是String类型,此处,为了验证原理,所以key存储了自定义对象
class Student{
String name;
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [name=" + name + "]";
}
//如果我们认为属性一致,则为同一个对象,则需要重写hashCode与equals
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
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;
Student other = (Student) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class Test2 {
public static void main(String[] args) {
Map<Student, Integer> map = new HashMap<Student, Integer>();
map.put(new Student("zs"), 13);
map.put(new Student("ls"), 15);
map.put(new Student("zs"), 18);
System.out.println(map);
//扩展说明:移除一个对象
map.remove(new Student("ls")); //移除时,重写了equals,也可以针对属性一致去移除
System.out.println(map);
}
}
- TreeMap集合
3.1 基本使用
TreeMap: Map接口的实现类
存储特点: key可排序,唯一 如果key重复,新的value替换旧的
分析TreeMap的存储原理:二叉树算法
说明:和TreeSet类似,因为TreeSet的具体实现是通过TreeMap完成的
public class Test1 {
public static void main(String[] args) {
Map<String, Integer> map = new TreeMap<String, Integer>();
map.put("cc", 11);
map.put("bb", 33);
map.put("aa", 22);
map.put("cc", 44);
System.out.println(map);
//循环遍历:
Set<String> keys = map.keySet();
for(String key:keys) {
System.out.println(key+"-->"+map.get(key));
}
Set<Entry<String, Integer>> set = map.entrySet();
for(Entry<String, Integer> entry:set) {
System.out.println(entry.getKey()+"==>"+entry.getValue());
}
}
}
3.2 TreeMap存储自定义对象
验证原理:
TreeMap存储自定义对象,查看结果
结果会报错
解决方式:
- 自然排序法—>实现Comparable接口
- 比较器法----->构造方法传比较器对象(匿名内部类)
class Person implements Comparable<Person>{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
//比较规则:先比较姓名的升序,姓名相同,再比较年龄的降序
if(this.name.equals(o.name)) {
return o.age-this.age;
}else {
return this.name.compareTo(o.name);
}
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class Test2 {
public static void main(String[] args) {
//Map<Person, Integer> map = new TreeMap<Person, Integer>();
Map<Person, Integer> map = new TreeMap<Person, Integer>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
//比较规则:先比较姓名的升序,姓名相同,再比较年龄的降序
if(o1.name.equals(o2.name)) {
return o2.age-o1.age;
}else {
return o1.name.compareTo(o2.name);
}
}
});
map.put(new Person("zs", 13), 66);
map.put(new Person("ls", 13), 66);
map.put(new Person("zs", 36), 11);
map.put(new Person("zs", 13), 25);
System.out.println(map);
}
}
3.3 其他类的相关操作
其他类的比较及操作:
HashMap VS Hashtable
HashMap: 不安全,但效率高的集合,key和value可以使用null
Hashtable:线程安全,效率低的集合,key和value都不能使用null
Properties: 是Hashtable的子类,常用于加载配置信息中
HashMap VS TreeMap
从执行效率方面考虑,肯定选择HashMap效率更高
如果需要实现排序,才选择TreeMap
public class Test1 {
public static void main(String[] args) throws FileNotFoundException, IOException {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("aa", 11);
map.put(null, 33);
map.put("cc", null);
System.out.println(map);
Map<String, Integer> map2 = new Hashtable<String, Integer>();
map2.put("aa", 11);
//map2.put(null, 33);
//map2.put("cc", null);
System.out.println(map2);
//Properties: 之前在System类中使用过
//Properties properties = System.getProperties(); //获取系统的配置属性
//加载配置文件信息: user.properties
Properties properties = new Properties();
//new一个IO流的子类对象,加载到Properties中,这样properties就有值了
properties.load(new FileInputStream("user.properties"));
//往往key为已知的,获取value值
System.out.println(properties.getProperty("name"));
}
}
3.4 集合相关汇总