List集合排序、自定义比较器排序

List集合排序

1、集合工具类(包装类)Collections.sort

使用Collections提供的sort方法,对集合进行排序

Collections.sort(list);

实现原理:
将list转成了数组对象后,调用了Array的sort方法,将数组排序,再用list的迭代器(注意不是collection迭代器)一个个得赋值回去,就使得传入的list变成了一个有序的list

  • 由于set,map都有SortedSet,TreeSet和SortedMap实现类,所以Collections中并没有对set和map支持sort方法
  • sort方法默认的顺序是升序,如果你想要降序排,你可以调用Collections中的另一个sort方法
public class SortListDemo {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		Random random = new Random();
		//随机生成一个数,作为list元素
		for(int i=0;i<10;i++){
			//向末尾添加随机的数
			list.add(random.nextInt(100));
		}
		System.out.println(list);
		//使用Collections提供的sort方法,对集合进行排序
		Collections.sort(list);
		System.out.println(list);
	}
}

Collection 与 Collections 的区别

1. java.util.Collection 是一个集合接口

它提供了对集合对象进行基本操作的通用接口方法
Collection接口在Java 类库中有很多具体的实现
Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式

2. java.util.Collections 是一个包装类

它包含有各种有关集合操作的静态多态方法
此类不能实例化,就像一个工具类,服务于Java的Collection框架

2、自定义排序

1. 比较器

Comparable接口:

Collections的sort方法是对集合元素进行自然排序
在使用Collections的sort排序的集合元素都必须是Comparable接口的实现类
该接口表示其子类是可比较的,因为实现该接口必须重写抽象方法 int compareTo(T t);

这个接口用于给需要排序的类来实现的,一旦实现,这个类就会按这个方式排序
比如说我们常见的String类就实现了这个接口,并重写了里面的compareTo
所以我们对字符串可以利用compareTo方法进行排序

Comparator接口(一般用这种):

一旦Java类实现了Comparable接口,其比较逻辑就已经确定(只能按写在自定义类中的算法排序)
如果希望在排序的操作中临时指定比较规则,可以采用Comparator接口回调的方式。
Comparator接口要求实现类必须重写其定义的方法 int compare(T o1,T o2)

通过比较器比较自定义类

自定义排序必须提供比较器
比较器为一个自定义的实现了比较器的类的实例化对象

自定义排序语法
Collections.sort(list,比较器);

2.实现方式

① 自定义一个比较器类,实现比较器的接口(Comparator 尖括号里面传入比较器比较的类)

注意:必须重写compare方法,返回值为int

然后使用Collections.sort时,在括号里传入需要排序的列表和new一个自定义比较器类的实例对象

Collections.sort(list, new ByAge());

② 匿名内部类(上班后常用,记得简写),实现原理同上

        //使用匿名内部类排序
		Comparator<Person> byAge = new Comparator<Person>(){
			@Override
			public int compare(Person o1, Person o2) {
				return o1.age-o2.age;
			}
		};
		//按照匿名内部类比较器规则进行年龄排序
		//这里只需要把刚才的内部类对象传递进来就行了
		Collections.sort(list,byAge);
		System.out.println(list);
		
		//上班后上述匿名内部类代码可以简化为
		Collections.sort(list,new Comparator<Person>(){
			public int compare(Person o1, Person o2){
				return o1.age-o2.age;
			}
		});
		System.out.println(list);
		
		//匿名内部类实现,按名字顺序比较
		Collections.sort(list,new Comparator<Person>(){
			public int compare(Person o1, Person o2) {
				//compareTo 按字典顺序比较两个字符串(字符编码)
				return o1.name.compareTo(o2.name);
			}
		});
		System.out.println(list);

3、自定义排序代码

package collection.comparator;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 自定义排序(通过比较器比较自定义类)
 * @author Tian
 *
 */
public class SortListDemo {
	public static void main(String[] args) {
		/*
		 * 对一组人进行自定义排序
		 */
		List<Person> list = new ArrayList<>();
		list.add(new Person("徐凤年",23,130));
		list.add(new Person("姜泥",20,96));
		list.add(new Person("裴南苇",32,98));
		list.add(new Person("洛阳",800,100));
		/*
		 * 自定义排序必须提供比较器
		 * 比较器为一个自定义的实现了比较器的类的实例化对象
		 */
		//Collections.sort(list,比较器);
		
		//按照自定义比较器规则进行年龄排序
		Collections.sort(list, new ByAge());
		System.out.println(list);
		
		//按照自定义比较器规则进行体重排序
		Collections.sort(list, new ByWeight());
		System.out.println(list);
		
		//使用匿名内部类排序
		Comparator<Person> byAge = new Comparator<Person>(){
			@Override
			public int compare(Person o1, Person o2) {
				return o1.age-o2.age;
			}
		};
		//按照匿名内部类比较器规则进行年龄排序
		//这里只需要把刚才的内部类对象传递进来就行了
		Collections.sort(list,byAge);
		System.out.println(list);
		
		//上班后上述匿名内部类代码可以简化为
		Collections.sort(list,new Comparator<Person>(){
			public int compare(Person o1, Person o2){
				return o1.age-o2.age;
			}
		});
		System.out.println(list);
		
		//匿名内部类实现,按名字顺序比较
		Collections.sort(list,new Comparator<Person>(){
			public int compare(Person o1, Person o2) {
				//compareTo 按字典顺序比较两个字符串(字符编码)
                //详情见拓展
				return o1.name.compareTo(o2.name);
			}
		});
		System.out.println(list);
		
		//按名字拼音的首字母排序
		//创建了一个字符串的列表,用来接收人类中的姓名
		List<String> str = new ArrayList<>();
		//循环遍历人类列表,将姓名放到字符串列表中
		for(Person p : list){
			str.add(p.name);
		}
		//使用比较器对名字列表进行排序
		/*
		 * Collator.getInstance(java.util.Locale.CHINA)
		 * 这个方法是
		 * Collator类调用了一下他的工厂方法(静态方法的一种常见用途)
		 * 该方法会返回一个比较器的对象,内部实现了按字符串首字符的拼音首字母排序
		 * 这个方法需要传入一个参数,语言包,我们这里传入的是中文
		 */
		Collections.sort(str,Collator.getInstance(java.util.Locale.CHINA));
		//输出排序后的字符串列表
		System.out.println(str);
		//问题:只能修改String列表,怎么把这个修改顺序的影响扩大到Person列表中呢
	}
}

/**
 * 根据年龄比较两人的比较器
 * 自定义比较器,实现比较器的接口
 * Comparator<Person>
 * 尖括号里面传入比较器比较的类
 */
class ByAge implements Comparator<Person>{
	/**
	 * 重写接口里面的比较方法
	 * 注意:该方法返回值需要有三个状态(0、正数、负数)
	 */
	@Override
	public int compare(Person o1, Person o2) {
		//按照两个人的年龄比较
//		if(o1.age == o2.age){
//			return 0; //返回0,表示人类o1与o2年龄一样
//		}else if(o1.age > o2.age){
//			return 1; //返回正数,表示01大于o2年龄
//		}else{
//			return -1; //返回负数,表示o1年龄小于o2年龄
//		}
		//可以优化为
		return o1.age-o2.age;
		//倒叙可以写为
		//return -(o1.age-o2.age);
	}
}

/**
 * 根据体重排序的比较器
 */
class ByWeight implements Comparator<Person>{
	/**
	 * 比较体重的比较器
	 * 体重是double类型,强转可能精度缺失(-0.5会变为0)
	 * 所以使用Math.signum用来取差的符号
	 * static double	signum(double d)
	 * 如果参数为零,则为零;如果参数大于零则为1.0;如果参数小于零,则为-1.0
	 * 获取符号后,我们可以进行强转,不会影响精度了
	 */
	@Override
	public int compare(Person o1, Person o2) {
		return (int) Math.signum(o1.weight-o2.weight);
	}
}

/**
 * 自定义类:人类(供测试用)
 * @author Tian
 *
 */
class Person{
	String name;
	int age;
	double weight;
	public Person(String name, int age, double weight) {
		this.name = name;
		this.age = age;
		this.weight = weight;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", weight=" + weight + "]";
	}
	
}

4、拓展

1. 字符串大小比较问题

字符串提供比较大小的方法
int compareTo(String anotherString)
按字典顺序比较两个字符串(按照字符编码进行比较)

比较两个字符串时:
先比较前两个字符大小(第一个汉字),如果可以比较出来就返回,不行的话就比较第二个
返回0,表示相等;返回正数表示第一个字符串大;返回负数,表示第一个字符串小

先比较前两个字符大小(第一个汉字),如果可以比较出来就返回,不行的话就比较第二个

public static void main(String[] args) {
		String s1 = "徐凤年";
		String s2 = "邓太阿";
		String s3 = "曹长卿";
		int n = s1.compareTo(s2);
		System.out.println(n);
	}

2. 按字符串首字符的拼音首字母排序

使用比较器对名字列表进行排序
Collator.getInstance(java.util.Locale.CHINA)
这个方法是
Collator类调用了一下他的工厂方法(静态方法的一种常见用途)
该方法会返回一个比较器的对象,内部实现了按字符串首字符的拼音首字母排序
这个方法需要传入一个参数,语言包,我们这里传入的是中文

        //按名字拼音的首字母排序
		//创建了一个字符串的列表,用来接收人类中的姓名
		List<String> str = new ArrayList<>();
		//循环遍历人类列表,将姓名放到字符串列表中
		for(Person p : list){
			str.add(p.name);
		}
		//使用比较器对名字列表进行排序
		/*
		 * Collator.getInstance(java.util.Locale.CHINA)
		 * 这个方法是
		 * Collator类调用了一下他的工厂方法(静态方法的一种常见用途)
		 * 该方法会返回一个比较器的对象,内部实现了按字符串首字符的拼音首字母排序
		 * 这个方法需要传入一个参数,语言包,我们这里传入的是中文
		 */
		Collections.sort(str,Collator.getInstance(java.util.Locale.CHINA));
		//输出排序后的字符串列表
		System.out.println(str);
		//问题:只能修改String列表,怎么把这个修改顺序的影响扩大到Person列表中呢
ps.工厂方法

静态方法的一种常见用途,用于构造对象

工厂方法的返回值为一个类的对象,用于使用一个类的静态方法完成创建一个我们需要的对象

比如上面的Collator.getInstance() 就是Collator中的静态方法,用来创建一个比较器对象

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
flex3的cookbook书籍完整版dpf(包含目录),目录是我花了两个多小时自己整理的,希望对大家有帮助。 目录: 第一章.Flex与ActionScript基础(3) 1.1节.用FlexBuilder创建Flex项目 1.2节.用FlexBuilder创建Flex库项目 1.3节.创建ActionScript项目 1.4节.在FlexBuilder设置MXML编译器选项 1.5节.在FlexBuilder外部编译Flex项目 1.6节.在MXML添加事件监听器 1.7节.设置子节点属性 1.8节.定义数组和对象 1.9节.在ActionScript设置变量的作用域 1.10节.在ActionScript创建组件 1.11节.使用事件冒泡机制 1.12节.使用代码隐藏模式分离MXML和ActionScript 1.13节.组件属性绑定 1.14节.使用自定义事件以及事件数据传递 1.15节.监听键盘事件 1.16节.定义方法参数 1.17节.检测对象数据类型 1.18节.接口的定义和实现 第二章. 控件与菜单(37) 2.1节. 监听按钮点击 2.2节. 创建一组状态按钮 2.3节. 使用ColorPicker设置Canvas颜色 2.4节. 使用SWFLoader载入SWF 2.5节. 设置组件的标签索引 2.6节. 设置控件的labelFunction 2.7节. 提供菜单数据 2.8. 动态填充菜单 2.9节. 为菜单类控件创建事件处理函数 2.10节. 显示一个通知窗口 2.11节. 使用Calendar控件 2.12节. 弹出窗口的显示和位置 2.13节. 自定义弹出式窗口边框 2.14节. 处理focusIn和focusOut事件 第三章容器(65) 3.1 节使用布局管理器布置子组件 3.2 节通过百分比方式配置容器的布局和尺寸 3.3节. 以不同的坐标系统跟踪鼠标位置 3.4 节在容器动态添加和移除子组件 3.5 节对容器使用基于约束的布局 3.6 节在容器内为子组件设置最大、最小尺寸 3.7 节为容器指定行和列的约束 3.8 节使用约束条件为文本创建排版流程(Layout Flows) 3.9 节在容器内控制滚动和溢出 3.10 节控制Box 组件的布局 3.11 节使用容器初始化 3.12 节创建TitleWindow 3.13 节通过LinkBar 控制ViewStack 3.14 节将ViewStack 的选索引数绑定到一个变量上 3.15 节使用延迟实例化提高启动效率 3.16 节创建并控制可调整大小的容器 3.17节在TabNavigator内创建、启用和禁用TAB组件(TabControls) 3.18 节使用可关闭Tabs 创建一个TabNavigator 3.19 节创建和控制Alert 3.20 节根据呼出组件设置对话框的尺寸和位置 3.21 节管理多个弹出对话框 3.22 节在容器滚动到某个指定的子组件 3.23 节使用IdeferredInstance 创建模板 3.24 节手动布局容器 3.25 节测量并改变容器尺寸 3.26 节控制子组件的可见性和布局 3.27 节用简单重组行为创建Tile 容器 3.28 节给Hbox 设置背景图片和圆角 3.29 节控制子组件的位置和滚动 第四章文本(121) 4.1节正确的设置一个文本对象的值 4.2节. 将TextInput绑定一个值 4.3节. 创建一个具有文字提示的文本输入框 4.4节. 创建一个合适的编辑器 4.5节. 确定用户电脑上安装的所有字体 4.6节. 创建一个自定义的TextInput 4.7节. 为一段文本设置风格属性 4.8节.在HTML里显示图片和SWF文档 4.9节. 在一个搜索域高亮显示用户输入 4.10节. 把字符当作独立图像处理 4.11节. 指定TextField的HTML样式 4.12节. 使用RichTextEditor 4.13节. 在HTML应用嵌入字体 4.14节. 给一个Text 组件的文本添加拖拽阴影 4.15节. 找出一个TextArea 最后显示的字符 第五章Lists,Tiles,和Trees(147) 5.1 节.创建可编辑的list 组件 5.2节.为List的某项设置图标 5.3 节. 为List的内容变更添加特效 5.4为TileList创建一个基本的条目渲染器 5.5节.为Tree设置XML数据 5.6节.为Tree创建项渲染器 5.7节.在Tree控件使用复杂数据对象 5.8节.只允许List的某一项可被选 5.9节.为List的项编辑器添加格式化和验证数据 5.10节.跟踪TileList所有被选的子节点 5.11节.使用和显示项渲染器的N

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值