TreeSet容器实现元素自排序

谈到TreeSet,首先要对比一下HashSet,二者都是Set集合的子类。Set集合有存储的数值不能重复的特点,其中,HashSet,取的数据不是按照怎样存就是怎样取,他的底层是一个HashMap做的数据存储,是一个Hash表,他实现去重的方式是:该HashSet容器中存储的无论是Java提供的系统类,比如,String,还是自定义类Person,Student,重写hashCode和equals方法后,可以实现去重功能。看String源码,可以知道String重写父类Object的hashCode和equals方法,所以当HashSet存储字符串时,可以实现去重功能

而TreeSet,其底层算法采用红黑树,也是二叉树的一种,树的左节点值小于同一个父节点的右节点值,他的特点是可以对插入的值进行有序输出。有两种实现方式,一个是自定义类实现比较器Comparable接口或Comparator接口,比如自定义Person类实现Comparable或Comparator接口。如果实现Comparable接口,就要重写Comparable接口的comparaTo方法,如果重写Comparator接口,就要重写compara方法。另一种方式是自定义一个比较器,该自定义比较器实现Comparator或Comparable接口。第一种方式,当一个类中同时实现Comparable和Comparator接口,那么以Comparator接口定义的比较规则优先

下面代码演示两种方式的实现:

第一种:自定义类实现比较器接口。

package com.jin.entity;

import java.util.Comparator;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Person implements Comparable<Object>, Comparator<Object>{

private String name;

private String pwd;

private Integer age;
/*
compareTo是Comparable接口方法
*/
@Override
public int compareTo(Object o) {
if(o instanceof Person) {
Person p = (Person) o;
/*
* 比较规则:先比较年龄,再比较姓名,最后比较密码
*/
if(this.age.equals(p.getAge())) {
if(this.name.equals(p.getName())) {
if(this.pwd.equals(p.getPwd())) {
return 0;
} else {
return this.pwd.compareTo(p.getPwd());
}
} else {
return this.name.compareTo(p.getName());
}
} else {
return this.age - p.getAge();
}
}
return -1;
}

/*
compare方法是Comparator接口方法
*/
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Person && o2 instanceof Person) {
Person s1 = (Person) o1;
Person s2 = (Person) o2;
/*
* 定义比较规则:先比较姓名,再比较年龄,最后比较密码
*/
if(s1.getName().equals(s2.getName())) {
if(s1.getAge().equals(s2.getAge())) {
if(s1.getPwd().equals(s2.getPwd())) {
return 0;
} else {
return s1.getPwd().compareTo(s2.getPwd());
}
} else {
return s1.getName().compareTo(s2.getName());
}
} else {
return s1.getAge() - s2.getAge();
}
}
return 0;
}
}

下面是TreeSet的应用:

TreeSet<Person> set = new TreeSet<Person>();

Person p1 = new Person("dbc", "admin", 22);
Person p2 = new Person("abc", "admin", 23);
Person p3 = new Person("abb", "admi", 23);
Person p4 = new Person("abc", "admin", 24);

set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);

System.out.println(set.size());
set.forEach(p -> { //p代表一个Person对象,用到了Java8的Lamda表达式
System.out.println(p); //由于同时用到了Comparable和Comparator接口,所以会优先按照Comparator接口定义的规则走
});

第二种方式:自定义一个比较器实现Comparator或Comparable接口
案例如下:

package com.jin.set;

import java.util.Comparator;

import com.jin.entity.Person;

public class MyComparator implements Comparator<Object> {

@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Person && o2 instanceof Person) {
Person s1 = (Person) o1;
Person s2 = (Person) o2;
/*
* 定义比较规则,年龄第一,名字第二,密码第三
*/
if(s1.getAge().equals(s2.getAge())) {
if(s1.getName().equals(s2.getName())) {
if(s1.getPwd().equals(s2.getPwd())) {
return 0;
} else {
return s1.getPwd().compareTo(s2.getPwd());
}
} else {
return s1.getName().compareTo(s2.getName());
}
} else {
return s1.getAge() - s2.getAge();
}
}
return -1;
}
}

下面是TreeSet的应用:

TreeSet<Person> set = new TreeSet<Person>(new MyComparator());

Person p1 = new Person("dbc", "admin", 22);
Person p2 = new Person("abc", "admin", 23);
Person p3 = new Person("abb", "admi", 23);
Person p4 = new Person("abc", "admin", 24);

set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);

System.out.println(set.size());
set.forEach(p -> {
System.out.println(p);
});

原文地址:https://www.cnblogs.com/jinshuaishuai/p/10936321.html

时间: 2024-10-13 00:00:40

TreeSet容器实现元素自排序的相关文章

《java入门第一季》之集合框架TreeSet存储元素自然排序以及图解

这一篇对TreeSet做介绍,先看一个简单的例子: * TreeSet:能够对元素按照某种规则进行排序. * 排序有两种方式 * A:自然排序: 从小到大排序 * B:比较器排序    Comparator import java.util.TreeSet; * TreeSet集合的特点:排序和唯一 * * 通过观察TreeSet的add()方法,我们知道最终要看TreeMap的put()方法.因为TreeMap是NavigableMap接口的实现类 */ public class TreeSe

使用TreeSet和Comparator,写TreeSetTest2 要求:对TreeSet中的元素1,2,3,4,5,6,7,8,9,10进行排列,排序逻辑为奇数在前偶数在后,奇数按照升序排列,偶数按照降序排列

/* * 使用TreeSet和Comparator,写TreeSetTest2 *要求:对TreeSet中的元素1,2,3,4,5,6,7,8,9,10进行排列, *排序逻辑为奇数在前偶数在后,奇数按照升序排列,偶数按照降序排列 */ import java.util.Comparator; import java.util.TreeSet; public class TreeTest2 { public static void main(String[] args) { // TODO Aut

对集合中的元素进行排序,接口Comparator&lt;T&gt;和Comparable&lt;T&gt;的使用

关于比较排序比较的接口 或者是类有:java.lang.Comparable<T>接口, 一个抽象类通过实现这个接口可以进行自然排序,也就是一个如果一个自定义类通过implements关键字实现Comparable<T>接口,并且要重写这个接口中的CompareTo()抽象方法,可以再这个方法中定义自己的比较规则:然后再向集合对象中添加元素的时候,就会自动调用compareTo()方法,对集合中的元素进行排序. 对于实现这个接口的类的对象,可以使用Collections类中的静态方

qsort 函数的使用——对普通数组、指针数组、二维数组中的元素进行排序

在ANSI C中,qsort函数的原型是 #include <stdlib.h> void qsort(void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *)); 解释:qsort函数对含有nmemb个元素的数组进行排序,而base指针指向数组的第一个元素.这个数组的元素个数由size指定. compar函数对qsort的比较操作进行定义,所以可以定制数字的比较,字符串的比较,甚至结构体

C++11新特性应用--介绍几个新增的便利算法(不更改容器中元素顺序的算法)

总所周知,C++ STL中有个头文件,名为algorithm,即算法的意思. The header<algorithm>defines a collection of functions especially designed to be used on ranges of elements. 所以,要八一八这个头文件中C++11新增的几个算法,今天主要描述的几个算法不改变容器中元素的顺序. 这里还要啰嗦一句,使用stl算法时,如果与lambda表达式组合使用,那么代码会更加简洁. find_

树状数组模拟3个元素的排序 Codeforces 12D Ball

http://codeforces.com/problemset/problem/12/d Ball time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output N ladies attend the ball in the King's palace. Every lady can be described with three val

C++ - 使用copy函数打印容器(container)元素

使用copy函数打印容器(container)元素 本文地址: http://blog.csdn.net/caroline_wendy C++可以使用copy函数输出容器(container)中的元素, 可以代替for循环. 头文件:  #include <algorithm> #include <iterator> 格式:  std::copy(cont.begin(), cont.end(),std::ostream_iterator<Type>(std::cout

使用函数指针,完成一个sort()函数,能对任何类型的数组元素进行排序: 回调函数 以及 memcpy ()原型实现

进来复习了一下C语言指针,一直没有写过太多关于函数指针的代码,而且对回调函数的理解一直都是在理论上,基本上没有太写过关于它的代码,进来得空,写了一个小程序加深下自己对回调函数和函数指针的理解. 问题描述: 编写一个sort()函数,使它能够对任何类型的数组元素进行排序. 下面是我写的代码: /* 使用函数指针的回调函数技巧,设计一个能排序int 和char 数组的sort()函数 */ #include<stdio.h> #include<stdlib.h> #include<

随机获取数组元素 和 数组元素随机排序

<script type="text/javascript"> //随机取得数组中的一个元素 function Rand(){ var arr=[11,22,33,44]; var a=Math.floor(Math.random()*arr.length);//Math.floor(Math.random()); //Math.floor()方法执行的是向下取整计算,它返回的是小于或等于函数参数,并且与之最接近的整数. //alert(Math.random()*arr.