Java实现储存对象并按对象某属性排序的几种方法示例
作者:.长卿 发布时间:2022-05-04 18:05:57
本文实例讲述了Java实现储存对象并按对象某属性排序的几种方法。分享给大家供大家参考,具体如下:
在编程的时候,经常会出现对某一种类的对象们按照某属性进行自定义的排序,比如:学生对象按照age大小排序。
有一种方法就是把age单独提出来排好序,然后按照ages数组的顺序把students重存一次。但是这样太繁琐了,有没有更好的方法呢?
有滴~
第一种,可以实现边添加边排序,需要用到TreeSet。
第二种,用数组存放对象们,但是不需单独取出某属性排列好再重存,而是在原数组上用比较器重新排一次序。需要用到Arrays.sort(arr,comparator)。
第三种,用集合类中的list的子类存放对象们,然后排序。需要用到Collections.sort(list,comparator)。
以下分别讨论:
一、TreeSet
创建:
序号 | 构造函数的说明 |
---|---|
1 | TreeSet () 此构造函数构造空树集,将在根据其元素的自然顺序按升序排序。 |
2 | TreeSet (集合 c) 此构造函数生成树的集合,它包含的元素的集合 c。 |
3 | TreeSet (比较器 comp) 此构造函数构造一个空树集,将根据给定的比较器进行排序。 |
增:
boolean | add(E e) 将指定的元素添加到这套,如果它已不存在。 |
boolean | addAll(Collection<? extends E> c) 在加入这一组指定的集合中添加的所有元素。 |
删:
boolean | remove(Object o) 从这一组中移除指定的元素,如果它存在。 |
void | clear() 从这一组中移除所有元素。 |
查:
Comparator<? super E> | comparator() 返回用于排序在这集,或空元素,如果这套使用自然排序其元素的比较。 |
boolean | contains(Object o) 如果此集合包含指定的元素,则返回true 。 |
boolean | isEmpty() 如果此集不包含任何元素,则返回true 。 |
Iterator<E> | iterator() 返回迭代器中这套以升序排序的元素。 |
| |
int | size() 在这套 (其基数) 中返回的元素的数目。 |
|
遍历:通过迭代器遍历。
Iterator it=treeset.iterator();
while(it.hasNext()){
//操作当前结点。
}
代码实现:
TreeSet是一个有序集合,TreeSet中的元素将按照升序排列。
TreeSet存储对象的时候, 可以排序, 其中Integer有默认排序方法, String有默认排序方法,,而自定义的类对象存储的时候则没有顺序,需要自定义排序算法。
如果想把自定义类的对象存入TreeSet进行排序,或者对int,String对象想定义自己的排序方法,有以下两种方法:
排序的第一种方式:
让元素自身具备比较性。让元素实现Comparable接口,覆盖compareTo方法,在方法内定义比较算法, 根据大小关系, 返回正数负数或零。在使用TreeSet存储对象的时候, add()方法内部就会自动调用compareTo()方法进行比较, 根据比较结果使用二叉树形式进行存储。
排序的第二种方式:
自定义比较器。 定义一个类实现Comparator接口,覆盖compare方法。将该Comparator接口子类对象传递给TreeSet集合构造函数。
第一种:类定义时实现Comparable接口,定义自身的比较算法。
此处以Person类为例,把人名和年龄作为对象属性,存放进treeset中,按照年龄的升/降序保存。
public class TreeSetTest {
public static void main(String[] args) {
TreeSet people=new TreeSet();
people.add(new Person("小明", 20));
people.add(new Person("小张", 30));
people.add(new Person("小刘", 18));
people.add(new Person("小林", 17));
people.add(new Person("小刘", 35));
Iterator it=people.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
class Person implements Comparable{//定义类时,实现比较接口
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:"+name+",年龄:"+age;
}
/*
compareTo(Object o):参数是从根节点开始依次传进来的结点,直到确定合适的位置用来安插新节点。
方法返回三个值,分别对应三种动作:返回1,则继续递进,把新结点与下一层的结点进行比较;
返回0,则该属性值不足以决定两结点位置区别,再定义其他属性的比较算法来进一步比较两对象;
返回-1,则新结点优先级大于当前层,往上一层比较;
*/
public int compareTo(Object o) {
Person curr=(Person) o;
//int result = this.age<curr.age?1:(this.age==curr.age?0:-1);//降序排列:新插入结点与当前比较层结点的属性比较,小则返回1,继续往下一层比较
int result = this.age>curr.age?1:(this.age==curr.age?0:-1);//升序排列:新插入结点与当前比较层结点的属性比较,大则返回1,继续往下一层比较
if(result==0){
result=this.name.compareTo(curr.name);//age相同时,则以姓名的字母序来排列。前面说过,int、string类型是有默认排列算法的,所以此处直接用
}
return result;
}
}
第二种:定义Comparator接口的实现类(比较器),在类中定义对象的比较算法。在创建Treeset时把比较器对象传进去。
public class TreeSetTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
TreeSet people=new TreeSet(new MyComparator());//把比较器对象作为TreeSet的构造函数参数
people.add(new Person("小明", 20));
people.add(new Person("小张", 30));
people.add(new Person("小刘", 18));
people.add(new Person("小林", 17));
people.add(new Person("小刘", 35));
Iterator it=people.iterator();//用迭代器遍历treeset
while(it.hasNext()){
System.out.println(it.next());
}
}
}
class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:"+name+",年龄:"+age;
}
}
class MyComparator implements Comparator{//实现Comparator接口,自定义比较器,实现compare方法定义比较算法
/*
compare(o1,o2):参数o1是待插入的结点,o2是从树根节点逐层遍历下来的结点,用于当前比较。
方法返回三个值,分别对应三种动作:返回1,则继续递进,把新结点与下一层的结点进行比较;
返回0,则该属性值不足以决定两结点位置区别,再定义其他属性的比较算法来进一步比较两对象;
返回-1,则新结点优先级大于当前层,往上一层比较;
*/
public int compare(Object o1, Object o2) {
Person p1=(Person)o1;
Person p2=(Person)o2;
int result=p1.age<p2.age?1:(p1.age==p2.age?0:-1);//降序排列
//int result=p1.age<p2.age?1:(p1.age==p2.age?0:-1);//升序排列
if(result==0){
result=p1.name.compareTo(p2.name);
}
return result;
}
}
二、用数组存放对象,用比较器改变sort()排序方法。
数组本身有默认的排序方法,针对int、string等基本类型有默认的sort()方法。而针对类对象的排序,可以给sort()方法传进一个比较器对象,赋予其排序的算法。
public class ArraysTest {
public static void main(String[] args) {
Person[] people=new Person[5];
people[0]=(new Person("小明", 20));
people[1]=(new Person("小张", 30));
people[2]=(new Person("小刘", 18));
people[3]=(new Person("小林", 17));
people[4]=(new Person("小刘", 35));
Arrays.sort(people,new MyCompare());//传进来一个比较器对象,使数组按比较器定义的规则来排序
for(Person i:people){
System.out.println(i);
}
}
}
class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:"+name+",年龄:"+age;
}
}
class MyCompare implements Comparator<Person>{//定义比较器
/*
重写比较方法compare(o1,o2):
方法传进来两个对象,用两个对象的某属性进行对比,返回一个int。
int>0,则o1排在o2后面;
int<0,则o1排在o2前面;
int=0,则维持原相对位置,即原来存放时o1、o2的前后地址顺序。
*/
public int compare(Person o1, Person o2) {
int result;
if(o1.age>o2.age){
result=1;
}
else if(o1.age<o2.age){
result=-1;
}
else{
result=0;
}
return result;
}
}
第三种:用list的子类:Vector、ArrayList存放对象们,调用Collections.sort(list,comparator)方法进行排序。
public class CollectionsTest {
public static void main(String[] args) {
Vector<Person> people=new Vector<>();//用向量保存对象
//ArrayList<Person> people=new ArrayList<>()://用ArrayList保存对象。
people.add(new Person("小明", 20));
people.add(new Person("小张", 30));
people.add(new Person("小刘", 18));
people.add(new Person("小林", 17));
people.add(new Person("小刘", 35));
Collections.sort(people,new MyComparator());//调用方法进行排序
Iterator it=people.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:"+name+",年龄:"+age;
}
}
class MyComparator implements Comparator<Person>{//实现Comparator接口,自定义比较器,实现compare方法定义比较算法
/*
compare(o1,o2):方法传进两个对象,根据某属性进行比较,返回一个int值。
int>0,o1排在o2后;
int<0,o1排在o2前;
int=0,维持原来存放时的相对位置。
*/
public int compare(Person p1, Person p2) {
int result=p1.age<p2.age?1:(p1.age==p2.age?0:-1);//降序排列
//int result=p1.age<p2.age?1:(p1.age==p2.age?0:-1);//升序排列
if(result==0){
result=p1.name.compareTo(p2.name);
}
return result;
}
}
希望本文所述对大家java程序设计有所帮助。
来源:https://www.cnblogs.com/ygj0930/p/5950971.html
猜你喜欢
- 本文实例为大家分享了Java金额大小写转换的具体代码,供大家参考,具体内容如下/** * @ClassName: NumberConver
- 首先安装consul环境,参照之前的文章:https://www.jb51.net/article/141789.htm项目规划,2个服务端
- 前言当初年少懵懂,那年夏天填志愿选专业,父母听其他长辈说选择计算机专业好。从那以后,我的身上就有了计院深深的烙印。从寝室到机房,从机房到图书
- JDBC操作MySQL在实际的企业级开发环境中,如果数据规模特S别大,此时采用传统的SQL语句去处理的话一般需要分成很多批次处理,而且很容易
- Spring 提供了自动代理机制,可以让容器自动生成代理,从而把开发人员从繁琐的配置中解脱出来 。 具体是使用 BeanPostProces
- 一、目的本篇文章的目的是记录本人使用flutter加载与调用第三方aar包。二、背景本人go后端,业余时间喜欢玩玩flutter。一直有一个
- 在模板文件的表达式中,可以使用“${T(全限定类名).方法名(参数)}”这种格式来调用Java类的静态方法。开发环境:IntelliJ ID
- 什么是FTPFTP(File Transfer Protocol)是TCP/IP网络上两台计算机传送文件的协议,使得主机间可以共享文件.可以
- Java8 LocalDateTime与timestamp转换将timestamp转为LocalDateTimepublic LocalDa
- spring的自动装配功能的定义:无须在Spring配置文件中描述javaBean之间的依赖关系(如配置<property>、&
- Java7 中 ConcurrentHashMapConcurrentHashMap 和 HashMap 思路是差不多的,但是因为它支持并发
- 1.Java进程的创建 Java提供了两种方法用来启动进程或其它程序: (1)使用Runtime的exec()方法 (2)使用Process
- 1、阿里云DNS的SDK依赖<dependency> <groupId>com.aliyu
- 前言 短时间提升自己最快的手段就是背面试题,最近总结了Java常用的面试题,分享给大家,希望大家都能圆梦大厂,加油,我命由我不由天
- 1、什么是servlet异步请求Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下:(1)、Servlet 接收
- 基本流foreach 实现了外部迭代,它是建立于集合的基础上;stream 流实现的是内部迭代中间操作与终端操作对任意集合使用 stream
- 需求使用 spring-boot 项目开发中,项目启动时“非常”慢的。如果每次修改代码或静态资源文件后都需要重新启动项目,这是多么痛苦的事。
- springmvc 使用map接收参数开发过程中有时候我们并不知道前端都会传递哪些参数给到后端. 为方便扩展接口功能, 在请求参数不改变的情
- 一、定时任务的使用场景和常见的定时任务某个时间定时处理某个任务、发邮件、短信、消息提醒、订单通知、统计报表等定时任务划分单机定时任务:单机的
- 当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。导致竞态条件发生的代码区称作临界区。在临界区中使用适当的同步就可以避免