JAVA数组排序&list排序&map排序&中文排序

本文详细介绍Java中数组和List的排序方法,包括基本数据类型和自定义对象的排序,并介绍了如何利用Comparable接口和Comparator接口实现复杂排序逻辑。此外,还探讨了Map的排序技巧。

 1.数组排序及list排序       

 

        在JAVA中对数组排序或list元素排序,JAVA提供了Arrays.sort()及Collections.sort(),使用者只要正确调用即可,不需要使用者自己写排序算法的实现。当然如果数据量大,并且要求效率高的话,还是需要自己选择适当排序算法的自己写代码实现。

 

         打开Collections.sort()源码,发现sort()重载了2次。

public static <T extends Comparable<? super T>> void sort(List<T> list) {
	Object[] a = list.toArray();
	Arrays.sort(a);
	ListIterator<T> i = list.listIterator();
	for (int j=0; j<a.length; j++) {
	    i.next();
	    i.set((T)a[j]);
	}
    }


public static <T> void sort(List<T> list, Comparator<? super T> c) {
	Object[] a = list.toArray();
	Arrays.sort(a, (Comparator)c);
	ListIterator i = list.listIterator();
	for (int j=0; j<a.length; j++) {
	    i.next();
	    i.set(a[j]);
	}
    }

       看源码知道Collections.sort()只对list类型进行排序,将list转换为数组,然后再用Arrays.sort()进行真正的排序。下面重点认识Arrays.sort()即可。

       看看Arrays.sort()进行了什么样的重载。

 

         Arrays.sort()支持所有基本数据类型的排序(byte,char,short,int,float,double,long)、Object对象排序及自定义的对象排序(需要实现Comparable接口或传入一个Comparator比较器,下面将会讲解)。

       对于元素类型是基本数据类型的数组,排序很简单,只需将数组传给Arrays.sort()即可。

package sort;

import java.util.Arrays;

public class JavaSort {
	public static void main(String[] args) {
		int[] x={5,2,10,45,6,4,69};
		System.out.println("排序前......");
		System.out.println(Arrays.toString(x));
		Arrays.sort(x);//排序,默认是从小到大
		System.out.println("排序后......");
		System.out.println(Arrays.toString(x));
	}
}

运行结果
排序前......
[5, 2, 10, 45, 6, 4, 69]
排序后......
[2, 4, 5, 6, 10, 45, 69]

 

     对象排序,则必须告诉JVM排序规则。

    

     如果你留意过Integer,Double,Long,String等这些类,会发现他们都实现了Comparable接口,Comparable接口定义如下

public interface Comparable<T> {
 public int compareTo(T o);
}

     

     Integer类中的compareTo()方法

public int compareTo(Integer anotherInteger) {
	int thisVal = this.value;
	int anotherVal = anotherInteger.value;
	return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
    }


    两对象比较,前者<后者,返回-1;前者>后者,返回1;前者=后者,返回0.

   

     下面写个小例子看下,两个user比较,按照age排序,如果age相等就按照姓名(中文)的拼音顺序排序。由于这例子中涉及到中文按拼音顺序排序。所以先看个中文排序例子。

      中文按照拼音顺序排序。

package sort;

import java.text.Collator;
import java.util.Arrays;

public class JavaSort {
	public static void main(String[] args) {
		Collator cmp=Collator.getInstance(java.util.Locale.CHINA);//获得中文比较器
		String[] x={"张三","李四","赵五","孙六"};
		System.out.println("排序前......");
		System.out.println(Arrays.toString(x));
		Arrays.sort(x,cmp);//告诉Arrays.sort要按照cmp这个比较规则进行比较
		System.out.println("排序后......");
		System.out.println(Arrays.toString(x));
		
	}
}

运行结果


排序前......
[张三, 李四, 赵五, 孙六]
排序后......
[李四, 孙六, 张三, 赵五]

 

      好了,已经知道中文按照拼音顺序排序的方法了,那么下面来看看user按照age排序,如果age相等,就按照name(中文)排序的小例子.

package sort;

import java.text.Collator;
import java.util.Locale;

public class User implements Comparable<User>{

	private String name;
	private int age;
	
	public User(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	@Override
	public int compareTo(User o) {
		int c1=this.age<o.getAge()?-1:(this.age==o.getAge()?0:1);//age compare
		if(c1!=0) return c1;//如果年龄不相等,则返回比较结果,姓名就不需要比较了
		return Collator.getInstance(Locale.CHINA).compare(this.name, o.getName());//返回姓名比较的结果
	}

	/**
	 * 为了方便打印user对象,重写toString
	 */
	public String toString(){
		return "{"+this.name+"  "+this.age+"}";
	}
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

package sort;

import java.text.Collator;
import java.util.Arrays;

public class JavaSort {
	public static void main(String[] args) {
		User[] users={
				new User("张三",20),
				new User("李四",25),
				new User("赵五",18),
				new User("孙六",18)
		};
		System.out.println("排序前......");
		System.out.println(Arrays.toString(users));
		Arrays.sort(users);
		System.out.println("排序后......");
		System.out.println(Arrays.toString(users));
		
	}
}


运行结果

 排序前......
[{张三  20}, {李四  25}, {赵五  18}, {孙六  18}]
排序后......
[{孙六  18}, {赵五  18}, {张三  20}, {李四  25}]

 

       上面的user类直接实现了Comparable接口,所以user对象可以进行比较。但是我们开发中,可能会遇到这种情况,比如User类是一个

JavaBean(POJO),初期是没有实现Comparable接口的,现在有需求需要user对象可以进行比较排序,先按照age排序,再按照name排序,不允许对User类进行修改。为了解决这种情况,JAVA提供了Comparator接口,定义如下

public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
}


        如果你细心,就会发现我上面贴出的Arrays.sort()重载的截图,发现有个sort(T[] a, Comparator<? super T> c);这个方法就是允许你传入一个自己定义的比较器。

package sort;


public class User {

	private String name;
	private int age;
	
	public User(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	
	/**
	 * 为了方便打印user对象,重写toString
	 */
	public String toString(){
		return "{"+this.name+"  "+this.age+"}";
	}
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

package sort;

import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;

public class UserComparator implements Comparator<User>{

	@Override
	public int compare(User u1, User u2) {
		int c1=u1.getAge()<u2.getAge()?-1:(u1.getAge()==u2.getAge()?0:1);//年龄比较
		if(c1!=0) return c1;
		return Collator.getInstance(Locale.CHINA).compare(u1.getName(), u2.getName());//返回姓名比较的结果
	}

}


package sort;

import java.text.Collator;
import java.util.Arrays;

public class JavaSort {
	public static void main(String[] args) {
		User[] users={
				new User("张三",20),
				new User("李四",25),
				new User("赵五",18),
				new User("孙六",18)
		};
		System.out.println("排序前......");
		System.out.println(Arrays.toString(users));
		Arrays.sort(users,new UserComparator());//这里的比较器也可以写成匿名类,不需要在写一个UserComparator类了
		System.out.println("排序后......");
		System.out.println(Arrays.toString(users));
		
	}
}

运行结果
 排序前......
[{张三  20}, {李四  25}, {赵五  18}, {孙六  18}]
排序后......
[{孙六  18}, {赵五  18}, {张三  20}, {李四  25}]

2.Map排序

       Map在实际开发中,会经常被使用到,特别是它的子类HashMap。HashMap是无序存放,就是说遍历得到的结果是随机的,无序的。那能不能对Map进行排序呢?JAVA中提供了TreeMap类,它是有序存放的,按集合中的key排序。先看看TreeMap例子

package sort;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class TreeMapTest {
	public static void main(String[] args) {
		Map<String,String> map=new TreeMap<String,String>();
		map.put("b", "李四");
		map.put("c", "赵五");
		map.put("a", "张三");
		map.put("d", "孙六");
		Iterator<String> it=map.keySet().iterator();
		while(it.hasNext()){
			String key=(String)it.next();
			System.out.println(key+"  "+map.get(key));
		}
	}
}

运行结果

a  张三
b  李四
c  赵五
d  孙六


   

 

        TreeMap可以对集合中的key排序,如果key是自己写的一个类呢?那么这时就需要new TreeMap()时,传入构造器。比如

Map<User,String> useMap=new TreeMap<User,String>(new UserComparator());


            TreeMap默认的是按key排序,那能否按value值排序呢?如果对Map的子类有所了解的同学,都知道map中的key-value都是保存在一个Entry类中,那key排序或者value排序,都可以通过Map.Entry<K,V>结合list进行排序。

          

package sort;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class TreeMapTest {
	public static void main(String[] args) {
		Map<String,String> map=new TreeMap<String,String>();
		map.put("b", "李四");
		map.put("c", "赵五");
		map.put("a", "张三");
		map.put("d", "孙六");
		List<Map.Entry<String,String>> mapList=new ArrayList<Map.Entry<String,String>>(map.entrySet());
		Collections.sort(mapList, new Comparator<Map.Entry<String,String>>(){
			@Override
			public int compare(Entry<String, String> o1,
					Entry<String, String> o2) {
				Collator cmp=	Collator.getInstance(Locale.CHINA);//中文按照拼音排序比较器
				return cmp.compare(o1.getValue(), o2.getValue());//如果想按key排序,改成getKey()就OK了
			}
			
		});
		for(Map.Entry<String, String> m:mapList){
			System.out.println(m.getKey()+"  "+m.getValue());
		}
		
	}
}

运行结果


b  李四
d  孙六
a  张三
c  赵五

    对HashMap,HashTable,LinkedHashMap等Map的子类其实都可以这样处理的。下面把上面程序的TreeMap改成 HashMap,按Key排序。

package sort;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class TreeMapTest {
	public static void main(String[] args) {
		Map<String,String> map=new HashMap<String,String>();
		map.put("b", "李四");
		map.put("c", "赵五");
		map.put("a", "张三");
		map.put("d", "孙六");
		List<Map.Entry<String,String>> mapList=new ArrayList<Map.Entry<String,String>>(map.entrySet());
		Collections.sort(mapList, new Comparator<Map.Entry<String,String>>(){
			@Override
			public int compare(Entry<String, String> o1,
					Entry<String, String> o2) {
				return o1.getKey().compareTo(o2.getKey());//如果想按value排序,改成getValue()就OK了
			}
			
		});
		for(Map.Entry<String, String> m:mapList){
			System.out.println(m.getKey()+"  "+m.getValue());
		}
		
	}
}

运行结果


a  张三
b  李四
c  赵五
d  孙六

 

 
 
 
 
 
 
 
 

 

 


&lt;think&gt; 我们参考了用户提供的多个引用,这些引用展示了在Java中对List进行自定义排序的不同方法,特别是针对List&lt;Map&gt;或List&lt;自定义对象&gt;的情况。用户的需求是&ldquo;对List&lt;Map&gt;对象数组进行自定义排序的实现方法&rdquo;。下面我们将结合引用内容,给出几种常见的实现方式。 根据引用[1],我们可以使用`Collections.sort`或List的`sort`方法,并传入自定义的`Comparator`。对于List&lt;Map&gt;,我们可以按照Map中某个键的值进行排序。 引用[3]展示了使用Java 8 Stream进行排序的方法,特别是对List&lt;Map&gt;按照某个字段(如&quot;Createtime&quot;)进行排序。 引用[4]则介绍了如何对多个动态属性字段进行排序,可以动态指定升序或降序。 下面我们分别介绍几种方法: ### 方法1:使用匿名内部类(传统方式) ```java List&lt;Map&lt;String, Object&gt;&gt; list = new ArrayList&lt;&gt;(); // 假设已经填充了数据 // 按照Map中的&quot;count&quot;字段降序排序 list.sort(new Comparator&lt;Map&lt;String, Object&gt;&gt;() { @Override public int compare(Map&lt;String, Object&gt; o1, Map&lt;String, Object&gt; o2) { // 假设count是Integer类型 Integer count1 = (Integer) o1.get(&quot;count&quot;); Integer count2 = (Integer) o2.get(&quot;count&quot;); // 降序排序 return count2.compareTo(count1); } }); ``` ### 方法2:使用Lambda表达式(Java 8及以上) ```java // 按照Map中的&quot;count&quot;字段升序排序 list.sort((o1, o2) -&gt; { Integer count1 = (Integer) o1.get(&quot;count&quot;); Integer count2 = (Integer) o2.get(&quot;count&quot;); return count1.compareTo(count2); }); ``` ### 方法3:使用Comparator.comparing(更简洁的方式) ```java // 升序排序 list.sort(Comparator.comparing(m -&gt; (Integer) m.get(&quot;count&quot;))); // 降序排序 list.sort(Comparator.comparing((Map&lt;String, Object&gt; m) -&gt; (Integer) m.get(&quot;count&quot;)).reversed()); ``` ### 方法4:多个字段动态排序(引用[4]的方法) 假设我们有一个动态的属性列表和对应的排序顺序(升序或降序),我们可以构建一个链式的Comparator。 ```java // 假设我们有如下动态排序条件 List&lt;String&gt; sortProperties = Arrays.asList(&quot;count&quot;, &quot;name&quot;); // 先按count排序,再按name排序 List&lt;Boolean&gt; sortOrders = Arrays.asList(true, false); // true表示降序,false表示升序 // 构建Comparator Comparator&lt;Map&lt;String, Object&gt;&gt; comparator = null; for (int i = 0; i &lt; sortProperties.size(); i++) { String property = sortProperties.get(i); boolean isDesc = sortOrders.get(i); Comparator&lt;Map&lt;String, Object&gt;&gt; currentComparator = Comparator.comparing(m -&gt; { Object value = m.get(property); // 这里需要根据实际类型处理,假设都是Comparable return (Comparable) value; }); if (isDesc) { currentComparator = currentComparator.reversed(); } if (comparator == null) { comparator = currentComparator; } else { comparator = comparator.thenComparing(currentComparator); } } // 使用这个comparator进行排序 if (comparator != null) { list.sort(comparator); } ``` ### 注意事项 1. 在比较时,需要确保Map中的键存在,且对应的值可以比较。如果值可能是null,需要做null处理。 2. 类型转换:从Map中取出的值是Object类型,需要根据实际情况转换为具体的可比较类型(如Integer、String等)。 3. 如果字段值可能是不同的类型(比如有的Map中count是Integer,有的是String),则需要额外处理。 ### 示例:处理可能的null值和不同类型 ```java list.sort((o1, o2) -&gt; { Object value1 = o1.get(&quot;count&quot;); Object value2 = o2.get(&quot;count&quot;); // 处理null值:将null视为最小 if (value1 == null &amp;&amp; value2 == null) return 0; if (value1 == null) return -1; // 升序时null排前面,降序则可能需要调整 if (value2 == null) return 1; // 确保它们是可比较的,比如都是Integer if (value1 instanceof Integer &amp;&amp; value2 instanceof Integer) { return Integer.compare((Integer) value1, (Integer) value2); } else { // 如果类型不同,可以转换为字符串比较,或者抛出异常等 return value1.toString().compareTo(value2.toString()); } }); ``` ### 总结 以上提供了多种对List&lt;Map&gt;进行自定义排序的方法,从传统的匿名内部类到Java 8的Stream和Lambda表达式,以及动态多字段排序。用户可以根据自己的Java版本和具体需求选择合适的方法。 &sect;&sect;相关问题&sect;&sect; 1. Java中如何对List&lt;自定义对象&gt;进行排序? 2. 在Java 8中,如何使用Stream对List进行多字段排序? 3. 在排序时如何处理null值? 4. Java的Comparator.comparing方法如何使用? &lt;/think&gt; 在 Java 中对 `List&lt;Map&gt;` 进行自定义排序,可以通过以下方法实现(基于 Java 8+ 的 Stream API 和 Lambda 表达式): ### 1. 单字段排序(按指定键的值排序) ```java List&lt;Map&lt;String, Object&gt;&gt; list = new ArrayList&lt;&gt;(); // 待排序列表 // 按 &quot;age&quot; 字段升序排序 List&lt;Map&lt;String, Object&gt;&gt; sortedList = list.stream() .sorted(Comparator.comparing(m -&gt; (Integer) m.get(&quot;age&quot;))) .collect(Collectors.toList()); // 按 &quot;salary&quot; 字段降序排序 List&lt;Map&lt;String, Object&gt;&gt; sortedList = list.stream() .sorted(Comparator.comparing(m -&gt; (Double) m.get(&quot;salary&quot;)).reversed()) .collect(Collectors.toList()); ``` ### 2. 多字段组合排序(优先级排序) ```java // 先按 &quot;department&quot; 升序,再按 &quot;salary&quot; 降序 List&lt;Map&lt;String, Object&gt;&gt; sortedList = list.stream() .sorted(Comparator .comparing(m -&gt; (String) m.get(&quot;department&quot;)) .thenComparing(Comparator.comparing(m -&gt; (Double) m.get(&quot;salary&quot;)).reversed()) ) .collect(Collectors.toList()); ``` ### 3. 动态字段排序(支持字段名和顺序动态传入) ```java // 定义排序规则:字段名列表 + 排序方向 List&lt;String&gt; sortFields = Arrays.asList(&quot;department&quot;, &quot;age&quot;); List&lt;Boolean&gt; ascendingFlags = Arrays.asList(true, false); // true=升序, false=降序 Comparator&lt;Map&lt;String, Object&gt;&gt; comparator = null; for (int i = 0; i &lt; sortFields.size(); i++) { String field = sortFields.get(i); Comparator&lt;Map&lt;String, Object&gt;&gt; current = Comparator.comparing(m -&gt; (Comparable) m.get(field) ); if (!ascendingFlags.get(i)) current = current.reversed(); comparator = (comparator == null) ? current : comparator.thenComparing(current); } List&lt;Map&lt;String, Object&gt;&gt; sortedList = list.stream() .sorted(comparator) .collect(Collectors.toList()); ``` ### 4. 传统 Comparator 实现(兼容 Java 7) ```java list.sort(new Comparator&lt;Map&lt;String, Object&gt;&gt;() { @Override public int compare(Map&lt;String, Object&gt; o1, Map&lt;String, Object&gt; o2) { // 按 &quot;name&quot; 字段升序 String name1 = (String) o1.get(&quot;name&quot;); String name2 = (String) o2.get(&quot;name&quot;); return name1.compareTo(name2); } }); ``` ### 关键注意事项 1. **类型转换**: 从 `Map` 获取值后需显式转换为实际类型(如 `(Integer) map.get(&quot;age&quot;)`) 2. **空值处理**: 建议使用 `Objects.compare()` 处理 `null` 值: ```java .sorted(Comparator.comparing(m -&gt; (String) m.get(&quot;department&quot;), Comparator.nullsLast(Comparator.naturalOrder()) )) ``` 3. **性能考虑**: 大数据量时使用 `parallelStream()` 并行排序 ### 示例场景 ```java List&lt;Map&lt;String, Object&gt;&gt; employees = new ArrayList&lt;&gt;(); employees.add(Map.of(&quot;name&quot;, &quot;Alice&quot;, &quot;age&quot;, 28, &quot;dept&quot;, &quot;HR&quot;)); employees.add(Map.of(&quot;name&quot;, &quot;Bob&quot;, &quot;age&quot;, 32, &quot;dept&quot;, &quot;IT&quot;)); // 按部门升序+年龄降序 List&lt;Map&lt;String, Object&gt;&gt; sorted = employees.stream() .sorted(Comparator .comparing(m -&gt; (String) m.get(&quot;dept&quot;)) .thenComparing(Comparator.comparing(m -&gt; (Integer) m.get(&quot;age&quot;)).reversed()) ) .collect(Collectors.toList()); ``` &gt; 引用说明:以上实现参考了 Java 的 `Comparator` 接口设计[^1],结合了 Stream API 的链式排序能力[^2][^3],并支持动态字段配置[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值