—————————————————————
——————————————
Set集合的方法和Collection框架的方法完全相同。
**Set:**元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。
········常用子类:
···············TreeSet: 底层数据结构是二叉树(又称为红黑树)
················HashSet:底层数据结构是哈希表
实现效果:存入时是无序的,但是在打印输出时是会对set集合中的元素进行排序
(按照自然顺序(ASCII),字符串可以称为字典顺序,总之是同一个意思。我这样说应该是不规范的)
对于取出:也是按照二叉树的从左到右依次增大的顺序来取的。
内部实现:无论前面的HashSet还是TreeSet,由于是不包含重复值的,所以其实内部都在调用用于比较的方法。
HashSet使用的比较方法是:HashCode()和equals();
TreeSet使用的方法是:
comparable接口的compareTo() 或者 Compartor接口的compare()方法。
前者,让元素具备比较性。即:Student s1,s2; s1.getName().compareTo(s2.getName())
而后者则是让容器具备比较性。(构造方法里接收一个比较器,初始化时就具有比较性。)
后者使用环境:当元素自身不具备比较性,或者具备的比较性无法实现排序,就让容器具备一个比较性。
案例一:实现存入到容器的学生按照年龄进行排序。
/*方法一:
1、使用让元素具备比较性的方法;(comparable接口的compareTo())
2、隐含则年龄相同需要判断姓名是否相同,相同则丢掉,否则按照字典顺序排序;
*/
class Student implements Comparable
{
private String name;
private int age;
//假设函数一初始化就指定姓名和年龄
Student(String name,int age)
{
this.name = name;
this.age = age;
}
//这里只写了get方法,用于获取。开发一般get和set都写
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
//重写比较方法,是不是自定义对象不包含该方法呢?
public int compareTo(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException("Error011:传入对象非Student类型!");
Student s = (Student)obj;
//这里注意在判断完年龄相同后,一定要判断一下次要元素。因为年龄相同的人有很多。
if(this.age>s.age)
return 1;
if(this.age==s.age)
{
return this.name.compareTo(s.name);
}
return -1;
/*
同时Integer整数类也重写了CompareTo()方法,
所以这里我们完全可以这么写:
(会提示API已经过时了。你懂的,该方法,在新版本可能不建议或者不可以使用了。)
int num=new Integer(this.getAge()).compareTo(new Integer(s.getAge()));
if(num==0)
{
//String类也实现了compaerTo()方法;
return this.getName().compareTo(s.getName());
}
return num;
*/
}
}
主函数:
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(new Student("lishi01",20));
ts.add(new Student("lishi01",21));
ts.add(new Student("lishi02",21));
ts.add(new Student("lishi05",20));
ts.add(new Student("lishi03",25));
ts.add(new Student("lishi04",21));
//再来一个重复元素
ts.add(new Student("lishi02",21));
Iterator it=ts.iterator();
while(it.hasNext())
{
Student s=(Student)it.next();
System.out.println(s.getName()+"......"+s.getAge());
}
}
}
案例二:实现存入到容器的学生按照姓名进行排序。
接下来使用创建比较器的方法:
------在TreeSet集合的API方法里有一个用于结构比较器的构造函数。所以这里我们创建一个比较器类,往容器内部传入该类对象。
Student类:
class Student
{
private String name;
private int age;
//假设函数一初始化就指定姓名和年龄
Student(String name,int age)
{
this.name = name;
this.age = age;
}
//这里只写了get方法,用于获取。开发一般get和set都写
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
主函数类:
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new MyComparator());
ts.add(new Student("lishi01",20));
ts.add(new Student("lishi01",21));
ts.add(new Student("lishi02",21));
ts.add(new Student("lishi05",20));
ts.add(new Student("lishi03",25));
ts.add(new Student("lishi04",21));
//再来一个重复元素
ts.add(new Student("lishi02",21));
Iterator it=ts.iterator();
while(it.hasNext())
{
Student s=(Student)it.next();
System.out.println(s.getName()+"......"+s.getAge());
}
}
}
自定义构造器类:
class MyComparator implements Comparator
{
//重写该容器的比较方法(被默认调用)
public int compare(Object obj1,Object obj2)
{
if(!(obj1 instanceof Student)||!(obj2 instanceof Student))
throw new RuntimeException("比较的对象非同一类型");
//强转为学生类
Student s1=(Student)obj1;
Student s2=(Student)obj2;
//同样这里要注意在判断完姓名相同后,一定要判断一下次要元素。因为姓名相同的人也有。
int num = s1.getName().compareTo(s2.getName());
if(num==0)
{
return s1.getAge()-s2.getAge();
}
return num;
}
}
结论:
①当两种排序方式都存在时,会默认按照比较器的方式进行排序。
②当想要按照插入顺序倒序打印时,将compare()或者compareTo()这两种方法的内部代码只写return -1;正序只写return 1;
③如果想要排序后再进行倒叙输出:该返回1的返回-1,该返回-1的返回1,就好了。
元素比较性并反向打印写法:
public int compareTo(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException("Error011:传入对象非Student类型!");
Student s = (Student)obj;
//---------------------Start-------------------------------------------
if(this.age>s.age)
return -1;
if(this.age==s.age)
{
return s.name.compareTo(this.name);
}
return 1;
//---------------------end------------------------------------------
}
自定义迭代器比较并反向打印写法:
public int compare(Object obj1,Object obj2)
{
if(!(obj1 instanceof Student)||!(obj2 instanceof Student))
throw new RuntimeException("比较的对象非同一类型");
//强转为学生类
Student s1=(Student)obj1;
Student s2=(Student)obj2;
//---------------------Start-------------------------------------------
int num = s1.getName().compareTo(s2.getName());
if(num==0)
{
return s1.getAge()-s2.getAge();
}
//---------------------end-------------------------------------------
return num;
}