[改善Java代码]非稳定排序推荐使用List

我们知道Set与List的最大区别就是Set中的元素不可以重复(这个重复指的equals方法的返回值相等),其他方面则没有太大的区别了,在Set的实现类中有一个比较常用的类需要了解一下:TreeSet,该类实现了类默认排序为升序的Set集合,如果插入一个元素,默认会按照升序排列(当然是根据Comparable接口的compareTo的返回值确定排序位置了),不过,这样的排序是不是在元素经常变化的场景中也适用呢?我们来看例子:

 1 import java.util.SortedSet;
 2 import java.util.TreeSet;
 3 
 4 public class Client {
 5     public static void main(String[] args) {
 6         SortedSet<Person> set = new TreeSet<Person>();
 7         //身高180CM
 8         set.add(new Person(180));
 9         //身高175CM
10         set.add(new Person(175));
11         
12         for(Person p:set){
13             System.out.println("身高:"+p.getHeight());
14         }
15     }
16     
17     static class Person implements Comparable<Person>{
18         //身高
19         private int height;
20         
21         public Person(int _age){
22             height = _age;
23         }
24         
25 
26         public int getHeight() {
27             return height;
28         }
29 
30 
31         public void setHeight(int height) {
32             this.height = height;
33         }
34 
35         //按照身高排序
36         public int compareTo(Person o) {
37             return height - o.height;
38         }
39 
40     }
41 }

 

程序输出:

身高:175
身高:180

 

这没有问题,随着时间的推移,身高175cm的人长高了10cm,而180cm却保持不变,那排序的位置应该改变一下吧,看代码(只需修改main方法):

 1     public static void main(String[] args) {
 2         SortedSet<Person> set = new TreeSet<Person>();
 3         // 身高180CM
 4         set.add(new Person(180));
 5         // 身高175CM
 6         set.add(new Person(175));
 7         // 身高最矮的人大变身
 8         set.first().setHeight(185);
 9         for (Person p : set) {
10             System.out.println("身高:" + p.getHeight());
11         }
12     }

 

程序输出:

身高:185
身高:180

很可惜,竟然没有重新排序,偏离了我们的预期。这正是下面要说明的问题,SortedSet接口(TreeSet实现了该接口)只是定义了在给集合加入元素时将其进行排序,并不能保证元素修改后的排序结果,因此TreeSet使用于不变量的集合数据排序,比如String、Integer等类型,但不适用于可变量的排序,特别是不确定何时元素会发生变化的数据集合。 
原因知道了,那如何解决此类重排序问题呢?有两种方式: 

(1).Set集合重排序 
重新生成一个Set对象,也就是对原有的Set对象重排序,代码如下:

 1 import java.util.ArrayList;
 2 import java.util.SortedSet;
 3 import java.util.TreeSet;
 4 
 5 public class Client {
 6     public static void main(String[] args) {
 7         SortedSet<Person> set = new TreeSet<Person>();
 8         // 身高180CM
 9         set.add(new Person(180));
10         // 身高175CM
11         set.add(new Person(175));
12         // 身高最矮的人大变身
13         set.first().setHeight(185);
14         //set重排序
15         set = new TreeSet<Person>(new ArrayList<Person>(set));
       //set = new TreeSet(set);该构造函数只是原Set的浅拷贝,如果里面有相同的元素,是不会重新排序的
16 for (Person p : set) { 17 System.out.println("身高:" + p.getHeight()); 18 } 19 } 20 21 static class Person implements Comparable<Person> { 22 // 身高 23 private int height; 24 25 public Person(int _age) { 26 height = _age; 27 } 28 29 public int getHeight() { 30 return height; 31 } 32 33 public void setHeight(int height) { 34 this.height = height; 35 } 36 37 // 按照身高排序 38 public int compareTo(Person o) { 39 return height - o.height; 40 } 41 42 } 43 }

 

程序输出:

身高:180
身高:185

就一句话即可重新排序。可能有读者会问,使用TreeSet(SortedSet< E > s)这个构造函数不是可以更好地解决问题吗?不行,该构造函数只是原Set的浅拷贝,如果里面有相同的元素,是不会重新排序的。 
(2).彻底重构掉TreeSet,使用List解决问题 
我们之所以使用TreeSet是希望实现自动排序,即使修改也能自动排序,既然它无法实现,那就用List来代替,然后再使用Collections.sort()方法对List排序.看代码:

 1 import java.util.ArrayList;
 2 import java.util.Collections;
 3 import java.util.List;
 4 import java.util.TreeSet;
 5 
 6 public class Client {
 7     public static void main(String[] args) {
 8         List<Person> list = new ArrayList<Person>();
 9         // 身高180CM
10         list.add(new Person(180));
11         // 身高175CM
12         list.add(new Person(175));
13         // 身高最矮的人大变身
14         list.get(1).setHeight(185);
15         
16         //排序
17         Collections.sort(list);
18         for (Person p : list) {
19             System.out.println("身高:" + p.getHeight());
20         }
21     }
22 
23     static class Person implements Comparable<Person> {
24         // 身高
25         private int height;
26 
27         public Person(int _age) {
28             height = _age;
29         }
30 
31         public int getHeight() {
32             return height;
33         }
34 
35         public void setHeight(int height) {
36             this.height = height;
37         }
38 
39         // 按照身高排序
40         public int compareTo(Person o) {
41             return height - o.height;
42         }
43 
44     }
45 }

 

程序输出:

身高:180
身高:185

 

两种方法都可以解决我们的困境,到底哪一个是最优的呢?对于不变量的排序,例如直接量(也就是8个基本类型)、String类型等,推荐使用TreeSet,而对于可变量,例如我们自己写的类,可能会在逻辑处理中改变其排序关键值的,则建议使用List自行排序。 
又有问题了,如果需要保证集合中元素的唯一性,又要保证元素值修改后排序正确,那该如何处理呢?List不能保证集合中的元素唯一,它是可以重复的,而Set能保证元素唯一,不重复。如果采用List解决排序问题,就需要自行解决元素重复问题(若要剔除也很简单,转变为HashSet,剔除后再转回来)。若采用TreeSet,则需要解决元素修改后的排序问题,孰是孰非,就需要根据具体的开发场景来决定了。

 

转载于:https://www.cnblogs.com/DreamDrive/p/5660201.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457645.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何访问另一台电脑的共享文件夹_如何远程控制另一台电脑

在工作中&#xff0c;我们时常需要远程控制一下另一台电脑&#xff0c;如果这两台计算机在局域网内可以通过远程桌面轻松实现&#xff0c;如果这两台计算机不在局域网内则通常需要借助第三方软件来实现。远程桌面使用分三步&#xff1a;1、被控制端要开启远程桌面功能&#xff…

10_JS数组

JS 数组 以索引为键的对象&#xff0c;性能高于对象 创建 new Array() var arr Array() for(var i 0;i<5;i){arr[i] i; };var arr Array(1,2,3,4,5,6)数组字面量 var arr [2,3,4,5,6,7,8];不同&#xff1a;传入一个整数时&#xff0c;new把这个数当作数组长度&…

微软Hololens学院教程- Holograms 101: Introduction with Device【微软教程已经更新,本文是老版本】...

这是老版本的教程&#xff0c;为了不耽误大家的时间&#xff0c;请直接看原文&#xff0c;本文仅供参考哦&#xff01;原文链接&#xff1a;https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/holograms_101 这篇文章将通过一个完整的实例来了解设备的核心特性&#…

python seaborn boxplot_python - 如何将文本框添加到Seaborn Boxplot? - 堆栈内存溢出

我试图在框图中插入一个文本框&#xff0c;但是出了点问题。 让我们先绘制箱线图&#xff1a;import pandas as pdimport matplotlib.pyplot as pltimport seaborn as sbdf_data pd.read_hdf(data.h5, keyfdf_data)##print(df_data)fig, (ax1, ax2) plt.subplots(1,2,gridspe…

JS_11正则表达式和字符串方法

正则表达式和字符串方法 正则表达式 创建正则对象 构造函数字面量 匹配模式 i&#xff1a;忽略大小写m&#xff1a;多行匹配g&#xff1a;全局匹配 正则语法 正则作用/a/检查是否有a/a|b/检查是否有a或b{}量词&#xff0c;如{1,3}匹配1到3次&#xff0c;{m,}匹配m次以上…

qtableview点击行将整行数据传过去_可以实时获取数据的Database Asset插件

前言&#xff1a;Goby之前开放的插件入口点较少&#xff0c;大家只能在扫描前、扫描后执行事件&#xff0c;无法参与扫描过程中来。为实现更多场景的应用及提高扫描效率&#xff08;如&#xff1a;后台爆破子域名等&#xff09;&#xff0c;Goby开放了一些新的API&#xff1a;事…

git 笔记

版本库1.repository在一个合适的地方&#xff0c;创建一个空目录$ mkdir learngit$ cd learngit$ pwd/User/leon/learngitpwd命令用于显示当前的目录&#xff0c;在我的电脑上&#xff0c;这个仓库位于/user/michael/learngit2.git init 将当前目录变成git 可以管理的仓库。$ g…

github 开源 代码 学习 集合(转载)

一个支持多种item类型的recycleView依赖注入库 1.通过注解的方式方便的把ViewHolder注入到recycleView中。 2.去除findViewByID等冗余操作。 3.去除编写adapter那些冗余逻辑&#xff0c;只需要编写proxy和holder即可快速的实现淘宝首页那样复杂的页面。https://github.com/s94…

JS_12 DOM

DOM 操作 HTML DOM Document Object Model&#xff0c;文档对象模型&#xff0c;用js操作文档对象 [外链图片转存失败(img-Dygj4uK9-1562680086020)(image/domtree.gif)] 节点&#xff1a;构成网页最基本的部分&#xff0c;网页的每一部分都是一个节点 文档节点&#xff1a;…

星星排序python_python中怎么实现星星排列

python中怎么实现星星排列&#xff1f;下面给大家带来几种排列阵型。星星阵型1def stars1(n):for i in range(1,n1):str "*"*iprint strif __name__ "__main__":stars1(5)星星阵型2def stars2(n):for i in range(1,n1):str **(n1-i)print strif __name_…

Kendo UI开发教程:Kendo UI模板概述

2019独角兽企业重金招聘Python工程师标准>>> Kendo UI框架提供了一个易用&#xff0c;高性能的JavaScript模板引擎。通过模板可以创建一个HTML片段然后可以和JavaScript数据合并成最终的HTML元素。Kendo 模板侧重于UI显示&#xff0c;支持关键的模板功能&#xff0c…

JS_13原型与原型链

原型与原型链 原型 每一个函数都有一个属性&#xff1a;prototype,默认指向object空对象&#xff0c;就是原型对象,原型对象有一个constructor属性&#xff0c;指向函数对象每一个实例化对象都有一个属性 proto ,默认指向构造函数的原型对象&#xff08;是构造函数原型对象的…

ajax数据保存及解析

1. $(#frmCam).serialize()&#xff1b;serialize() 方法通过序列化表单值&#xff0c;创建 URL 编码文本字符串。 2.自动对应ID和值 window.camConfig [<%(camConfig) %>]; if (camConfig.length>0) { for(var property in cam…

python和revit_pyRevit系列教程1

有没有人和我一样&#xff0c;想要自己写一些小功能来用(zhuang)用(bi)&#xff0c;但苦于C#太难学了&#xff0c;不得不作罢。话说感受过Python的美好&#xff0c;怎么能忍受C#的大括号&#xff01;毕竟人生苦短&#xff0c;我用Python&#xff01;好吧&#xff0c;我承认是我…

【leetcode】104. Maximum Depth of Binary Tree

1. 题目 Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 2. 思路 递归到左、右子树的max值&#xff0c;1. 3. 代码 /*** Definition for a binary tree …

JS_14 执行上下文与执行上下文栈

执行上下文和执行上下文栈 变量提升和函数提升 变量提升 所用使用var定义的变量&#xff0c;在程序运行前会被先定义&#xff0c;并赋初值为underfind&#xff0c;保存到其执行上下文中 函数提升 在调用函数&#xff0c;执行函数体之前&#xff0c;会先执行函数定义&#xff…

shell编程-变量

1.Bash用户自定义变量 【局部变量】 【按数据存储分类】&#xff1a;整型、浮点型、字符串型、日期型 【变量定义】&#xff1a;x5,y6,z$x$y56,m$(($x$y))11 【Bash变量默认都为字符串型&#xff0c;等号左右不可以有空格】 【变量叠加】&#xff1a;x"$x"123,x${x}3…

JS_15作用域与作用域链

作用域与作用域链 作用域 类别 全局作用域函数作用域块作用域&#xff1a;Es6时出现&#xff0c;之前没有 作用域与执行上下文 区别 创建时机不同 全局作用域外&#xff0c;每个函数都有自己的作用域&#xff0c;作用域在函数创建时就创建了&#xff0c;而不是在调用时全局执…

多线程调用同一个对象的方法_多线程之如何创建和使用线程

一、创建线程和使用线程方式1.1 继承Thread让线程类继承自Thread类&#xff0c;然后重写run()&#xff0c;把需要多线程调用的代码放到run()中。但是需要开启线程的时候不能调用run方法&#xff0c;而是需要调用start()方法。/*** 本类用于演示第一种实现多线程的方式*/ class…

struts2的namespace的问题

<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <inc…