java毕向东听课笔记25(集合框架-Set集合TreeSet)

TreeSet:可以对Set集合中的元素进行排序。

例:存放自定义对象

import java.util.*;
/*
需求:往TreeSet集合中存储自定义对象--学生
想按照学生的年龄进行排序

*/
class Student{
	private String name;
	private int age;

	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	public String getName(){
		return name;
	}

	public int getAge(){
		return age;
	}
}

class TreeSetDemo{
	public static void main(String[] args){
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi01",40));

		Iterator it = ts.iterator();

		while(it.hasNext()){
			Student stu = (Student)it.next();
			sop(stu.getName()+"::"+stu.getAge());
		}
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

然而输出结果是:

这是因为TreeSet会自动排序,然而我们存放的自定义对象没有比较性,所以报错。

解决方法:让Student类实现Comparable接口,强制让学生具备比较性

import java.util.*;
/*
需求:往TreeSet集合中存储自定义对象--学生
想按照学生的年龄进行排序

*/
class Student implements Comparable{
	private String name;
	private int age;

	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj){
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;
		return this.age-s.age;
	}
	public String getName(){
		return name;
	}

	public int getAge(){
		return age;
	}
}

class TreeSetDemo{
	public static void main(String[] args){
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi01",40));

		Iterator it = ts.iterator();

		while(it.hasNext()){
			Student stu = (Student)it.next();
			sop(stu.getName()+"::"+stu.getAge());
		}
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

如果年龄相同,姓名不同,会出现什么情况呢?

import java.util.*;
/*
需求:往TreeSet集合中存储自定义对象--学生
想按照学生的年龄进行排序

*/
class Student implements Comparable{
	private String name;
	private int age;

	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj){
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;
		return this.age-s.age;
	}
	public String getName(){
		return name;
	}

	public int getAge(){
		return age;
	}
}

class TreeSetDemo{
	public static void main(String[] args){
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi01",40));
		ts.add(new Student("lisi08",40));

		Iterator it = ts.iterator();

		while(it.hasNext()){
			Student stu = (Student)it.next();
			sop(stu.getName()+"::"+stu.getAge());
		}
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

发现新元素没有存进来,这是因为根据比较规则,相同年龄即代表同一元素,根据不可重复性,该元素没有存进来。怎么解决?如下:

import java.util.*;
/*
需求:往TreeSet集合中存储自定义对象--学生
想按照学生的年龄进行排序

*/
class Student implements Comparable{
	private String name;
	private int age;

	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj){
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;
		if(this.age>s.age)
			return 1;
		if(this.age==s.age){
			return this.name.compareTo(s.name);
		}
		return -1;
	}
	public String getName(){
		return name;
	}

	public int getAge(){
		return age;
	}
}

class TreeSetDemo{
	public static void main(String[] args){
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi01",40));
		ts.add(new Student("lisi08",40));

		Iterator it = ts.iterator();

		while(it.hasNext()){
			Student stu = (Student)it.next();
			sop(stu.getName()+"::"+stu.getAge());
		}
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

总结:排序时,当主要条件相同时,一定要判断次要条件

---------------------------------------------------------------------------------

TreeSet底层的数据结构为二叉树。保证元素唯一性的依据:compareTo方法return 0.

TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法,这种方式也称为元素的自然顺序,或者叫做默认顺序

TreeSet集合的第二种排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式

import java.util.*;

/*
当元素自身不具备比较性,或者具备的比较性不是所需要的
这时需要让容器自身具备比较性。
定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数

当两种排序都存在时,以比较器为主

定义一个类,实现Comparator接口,覆盖compare方法(注意:comparable里面才是compareTo方法)
*/
class Student implements Comparable{
	private String name;
	private int age;

	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj){
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;
		if(this.age>s.age)
			return 1;
		if(this.age==s.age){
			return this.name.compareTo(s.name);
		}
		return -1;
	}
	public String getName(){
		return name;
	}

	public int getAge(){
		return age;
	}
}
class TreeSetDemo2{
	public static void main(String[] args){
	TreeSet ts = new TreeSet();

	ts.add(new Student("lisi02",22));
	ts.add(new Student("lisi007",20));
	ts.add(new Student("lisi007",21));
	ts.add(new Student("lisi09",19));
	ts.add(new Student("lisi01",40));
	ts.add(new Student("lisi08",40));

	Iterator it = ts.iterator();

		while(it.hasNext()){
			Student stu = (Student)it.next();
			sop(stu.getName()+"::"+stu.getAge());
		}
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

class MyCompare implements Comparator{
	public int compare(Object o1,Object o2){
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;

		int num = s1.getName().compareTo(s2.getName());
		if(num==0){
			if(s1.getAge()>s2.getAge())
				return 1;
			if(s1.getAge()==s2.getAge())
				return 0;
			return -1;//更简单的写法:return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}
		return num;
	}
}

-----------------------------------------------------------------------

TreeSet练习:按照字符串长度排序

一开始的代码如下:

/*
字符串本身具备比较性,但是它的比较方式不是所需要的,这时就只能使用比较器
*/

import java.util.*;

class TreeSetTest{
	public static void main(String[] args){
		TreeSet ts =new TreeSet();

		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("z");
		ts.add("hahaha");

		Iterator it = ts.iterator();

		while(it.hasNext()){
			sop(it.next());
		}
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

结果为

显然不是我们想要的。

/*
字符串本身具备比较性,但是它的比较方式不是所需要的,这时就只能使用比较器
*/

import java.util.*;

class TreeSetTest{
	public static void main(String[] args){
		TreeSet ts =new TreeSet(new StringLengthComparator());

		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("z");
		ts.add("hahaha");

		Iterator it = ts.iterator();

		while(it.hasNext()){
			sop(it.next());
		}
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}
class StringLengthComparator implements Comparator{
	public int compare(Object o1,Object o2){
		String s1 = (String)o1;
		String s2 = (String)o2;
		return s1.length()-s2.length();
	}
}

可以优化的地方:当出现相同长度,不同内容的字符串时,会因为长度相同而被视为相同元素,不被存储进来,所以在实现比较器接口的类中应该判断当长度相同时,比较字符串内容。即:

class StringLengthComparator implements Comparator{
	public int compare(Object o1,Object o2){
		String s1 = (String)o1;
		String s2 = (String)o2;
		//return s1.length()-s2.length();
		int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
		if(num==0)
			return s1.compareTo(s2);
		return num;
	}
}
时间: 2024-10-18 19:26:27

java毕向东听课笔记25(集合框架-Set集合TreeSet)的相关文章

JAVASE02-Unit04: 集合框架 、 集合操作 —— 线性表

Unit04: 集合框架 . 集合操作 -- 线性表 操作集合元素相关方法 package day04; import java.util.ArrayList; import java.util.Collection; import day02.Point; /** * 操作集合元素相关方法 * @author adminitartor * */ public class Collection_Remove { public static void main(String[] args) { C

java集合框架--Map集合

1.Map集合的概述 Map集合是将键映射到值的对象.一个映射不能包含重复的键.每个键最多只能映射到一个值. 2.Map接口和Collection接口的不同? Map集合存储元素是成对出现的,Collection集合存储元素是单独出现的. Map集合的键是唯一的,值是可重复的. Collection集合的子接口Set是唯一的,List是可重复的. Map集合的数据结构值针对键有效,和值无关,而Collection接口的数据结构是针对元素有效. 3.Map集合示例及功能 package cn; i

JAVA-初步认识-常用对象API(集合框架-Map集合常见子类对象)

一. 说完了map集合,顺便说些小东西. map集合常用的子类: hashtable研究的就是数据结构,哈希在1.0就出来了,那是还没有table.当时,单列集合只有vector,双列集合就是hashtable.内部结构就是哈希表.是同步的.hashmap和hashtable有区别么,效率高低不再多说.下图是hashmap的API注解,是不同步的. hashtable,它不支持空键和空值.面试的时候它们之间的区别. 上面截图的体系和一个集合体系很像,就是set集合,hashset和treeset

java集合框架--Set集合

1.Set集合概述 一个不包含重复元素的集合. 2.代码引入 package com; import java.util.HashSet; import java.util.Set; /**  * Collection  *  List    有序(存储顺序和取出顺序一致),可重复  *  Set  无序(存储顺序和取出顺序不一致),唯一  *  虽然Set集合的元素无序,但是,作为集合来说,它肯定有自己的存储顺序,  *  我们存储元素的时候可能和它内存的存储元素顺序相同.  *   * Ha

java 集合框架 Set 集合之 HashSet TreeSet

set: 特点:无序的,长度可变的,不可重复的. HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单. 底层数据结构是 hash 表. HashSet 保证元素的唯一性是通过元素的两个方法,hashCode 和 equals 来完成. -----如果元素的 HashCode 值相同,才会判断 equals 是否为true. -----如果元素的 HashCode 值不

集合框架(List集合的特有功能概述和测试)

package cn.itcast_03; import java.util.ArrayList; import java.util.List; /* * List集合的特有功能: * A:添加功能 * void add(int index,Object element):在指定位置添加元素 * B:获取功能 * Object get(int index):获取指定位置的元素 * C:列表迭代器 * ListIterator listIterator():List集合特有的迭代器 * D:删除功

集合框架(List集合的特有遍历功能)

package cn.itcast_03; import java.util.ArrayList;import java.util.List; /* * List集合的特有遍历功能: *   size()和get()方法结合使用 */public class ListDemo2 { public static void main(String[] args) {  // 创建集合对象  List list = new ArrayList(); // 添加元素  list.add("hello&q

集合框架(List集合的特点)

List接口概述(它的元素可重复) 有序的 collection(也称为序列).此接口的用户可以对列表中每个元素的插入位置进行精确地控制.用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素. 与 set 不同,列表通常允许重复的元素. List案例 存储字符串并遍历 存储自定义对象并遍历 package cn.itcast_01; import java.util.ArrayList; import java.util.Iterator; import java.util.

集合框架-Collection集合

集合有两大类:Collection和Map, 集合的由来:我们用对象来封装数据,对象多了也要存储起来,如果对象的个数不确定,就使用集合容器进行存储. 集合的特点:所有集合类都位于java.util包下.集合中只能保存对象(保存对象的引用变量,集合存储的是对象的地址),不可以存储基本数据类型值,集合长度的是可变的,集合可以存储不同类型的对象 为什么会出现这么多容器?每个容器对数据存储的方式不同,这个方式就称为:数据结构. 集合与数组的区别:数组长度不可变,数组对象必须是同种类型. 集合Collec