java排序问题,comparator接口,求高手

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java排序问题,comparator接口,求高手相关的知识,希望对你有一定的参考价值。

list里存着("张三","李四","王五","张六"),要求按姓名首字母排序,并且返回这个排序以后的下标!!!
比如这个集合,返回的应该是 1 2 3 0 求高手指点怎么用comparator接口啊!!!
map 解决不了,因为这里的名字可能会重复,已经试过了,能贴出代码的+20分

首先,比较Comparable和Comparator的区别

Comparable & Comparator 都是用来实现集合中的排序的,只是 Comparable 是在集合内部定义的方法实现的排序,Comparator 是在集合外部实现的排序,所以,如想实现排序,就需要在集合外定义 Comparator 接口的方法或在集合内实现 Comparable 接口的方法。

Comparable 是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作);

而 Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。

可以说一个是类自已完成比较,一个是外部程序实现比较的差别而已。

用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。

从操作上:Comparable 需要在被排序的类中实现其接口,而Comparator 是在被排序类的外部实现其接口即可.这样可以看出Comparable操作更简单,而Comparator操作复杂但是可以实现多种不同的排序方案.

比如:你想对整数采用绝对值大小来排序,Integer 是不符合要求的,你不能去修改 Integer 类去改变它的排序行为,只要使用一个实现了 Comparator 接口的对象来实现控制它的排序就行了。

实现Comparator接口,实现排序

在Comparator接口里,只有一个方法是需要实现的:
Java代码
int compare(Object o1,Object o2);

int compare(Object o1,Object o2);
提示:如果o1小于o2,返回一个负数;如果o1大于o2,返回一个正数;如果他们相等,则返回0;

注意:compare方法一定要是对称的,意思是compare(a,b)返回的结果要跟compare(b,a)相反。相反的结果意味着,要么返回的值带有不同的正负号,要么都是0。注意,象compare(a,b)返回4而compare(b,a)返回-2这样的情况是合法的。方法里常常可能抛出异常,在这个方法里抛出异常也要是对称的。如果调用compare(a,b)时抛出了一个ClassCastException异常,那么调用compare(b,a)时也必须抛出一个ClassCastException异常。

另外:任何你准备重用的Comparator都必须是可序列化的。TreeSet和TreeMap类存储Comparator以便进行比较,因此为了这两个类能被序列化,它们使用的Comparator也必须能被序列化。

Comparator接口,通常被Collections.sort方法使用,它是JAVA中需要了解的一个很重要的部分,因为它有一些重要的契约义务.追问

我要的不是排序后的数组,而是排序后的下标

参考技术A 这个严格按照拼音顺序进行排序,试一下吧
import java.util.*;
class Test

public static void main(String[] args)

int index=0;
ArrayList<String> al=new ArrayList<String>();
al.add("张三");
al.add("李四");
al.add("王五");
al.add("张六");
Collections.sort(al,new SortComparator());
for(String name : al)

System.out.println(name);
System.out.println(name+"的下标为:"+(index++));




class SortComparator implements Comparator<Object>

public int compare(Object o1,Object o2)

try

byte[] buf1 = ((String) o1).getBytes("GB2312");
byte[] buf2 = ((String) o2).getBytes("GB2312");
int size = Math.min(buf1.length, buf2.length);
for (int i = 0; i < size; i++)

if (buf1[i] < buf2[i])
return -1;
else if (buf1[i] > buf2[i])
return 1;

return buf1.length - buf2.length;

catch(Exception ex)

return 0;


追问

哥们,你这个可以排序,问题是我要的下标是原来数组中的下标,你这个下标是0123,我要的下标是1230啊

追答

改好了,你再看一下吧
import java.util.*;
class Test

public static void main(String[] args)

ArrayList al1=new ArrayList();
al1.add("张三");
al1.add("李四");
al1.add("王五");
al1.add("张六");
ArrayList al2=new ArrayList(al1);
Collections.sort(al2,new SortComparator());
for(String name : al2)

System.out.println(name);

Iterator it=al1.iterator();
for(int i=0;i

public int compare(Object o1,Object o2)

try

byte[] buf1 = ((String) o1).getBytes("GB2312");
byte[] buf2 = ((String) o2).getBytes("GB2312");
int size = Math.min(buf1.length, buf2.length);
for (int i = 0; i buf2[i])
return 1;

return buf1.length - buf2.length;

catch(Exception ex)

return 0;


追问

嗯 你的代码基本实现了,最后用的是查找的算法,但是我的名字集合里有重复值,例如
("张三","李四","王五","张六","李四","王五"),这样的算法会造成下标重复啊,还有其他的办法吗

本回答被提问者采纳
参考技术B 中文字符串.getBytes()得到字节数组每个元素比较可以比较中文,是比较一个汉字拆分成的每个字节?调用tocharArray()得到的字符比较试了下发现不行,这个是什么原因?求指教。 参考技术C 如楼上说的Collator可以搞定追问

那是我自己说的

追答

搞错。。。那还有啥问题~?

追问

我要返回排序以后的集合的,原下标

追答

你要的不是对集合里面的内容排序么?。。你可以定义一个数组,长度,内容与你的集合一样,,然后写个冒泡算法。。。得出来的就是排序好的集合了。。不明白你非要那个下标来干嘛,
真的要那个下标你就再定义一个数组,放下标的,比较的时候,也把这个放下标的数组也一起比较,冒泡算法跑完了,你要的下标也有了

追问

冒泡有比较大小,整数就不说,中文怎么比较?
comparator可以比较中文,但是又返回不了下标,怎么办?

追答

冒泡不止是比较数字的吧。。。转换一下就可以了啊。。原来是array[x+1]>array[x]就将他们位置互换。。。你改成Collator.getinstance().compare(array[x+1],array[x])>1这样是一样的概念。。。

参考技术D 这个看API就行了追问

看不懂

追答

comparator接口我倒是知道怎么用,不过按拼音首字母的话就不是能随便写得出来的了,需要做汉字和拼音的映射,这都用别人写的包才行啊

追问

你这水平不行
Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);
Arrays.sort(a, cmp);
这样就可以对中文首字母排序,我只是不知道如何返回下标

追答

还是用说的吧,工具没开。
实现Comparator接口,实现其compare方法,Comparator接口需要指定泛型,比如你list里面的每个元素都是一个User对象的话,class MyComparator implements Comparator*******;
compare方法有两个参数,指定了泛型过后,参数类型就是你指定的类型,比如这儿compare方法就是 public int compare(User o1, User o2)****;compare里面怎么比较就随便你了,原则就是如果o1>o2,返回1,o1<o2返回-1(其实只要是正整数和负整数都行),o1==o2返回0,。完了~

Comparable接口与Comparator接口的比较————Comparable接口详解

Comparable接口位于:java.lang包中。

Comparable接口:
  1. 实现了这个接口的类,会被强制进行自然排序。
    问题又来了:那什么是自然排序呢?
      自然排序:就是字典序排序,不分大小写。例如:a、A都排在b、B之前。
    做个简单的测试吧:
    现在有个需求,需要让你把用户进行自然排序。So,亲爱的小伙伴们,这应该
    怎么做呢?
    思路:创建一个用户类(User),且此类实现了Comparable接口,然后进行测试。
    记住了呦:
      Collections.sort();可以对列表进行排序。
      Arrays.sort();可以对数组进行排序哦。
    嘿嘿,Let‘s do a test!

  下面是User类的代码:

 package test;

public class User implements Comparable<User>{

	private String name;
	private Integer age;
	
	public User(String name, Integer age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

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

	public Integer getAge() {
		return age;
	}

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

	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + "]";
	}

	/*
	 * 先比较name,
	 * 		大于,返回1
	 * 		等于,接着比较age
	 * 			age:大于,返回1
	 * 				等于,返回0
	 * 				小于,返回-1
	 * 		小于:返回-1
	 * (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(User o) {
		int flag = 0;
		flag = this.getName().compareTo(o.getName());
		if(flag == 0) {
			flag = this.getAge().compareTo(o.getAge());
			return flag;
		}else {
			return flag;
		}
	}

}

 

  下面是做测试的代码UserTest:

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class UserTest {
	
	public static void print(List<User> list) {
		for(User u : list) {
			System.out.println(u);
		}
	}
	
	public static void print(User[] array) {
		for(int i=0; i<array.length; i++) {
			System.out.println(array[i]);
		}
	}
	
	public static void main(String[] args) {
		
		List<User> users = new ArrayList<User>();
		users.add(new User("a",12));
		users.add(new User("C",25));
		users.add(new User("B",12));
		users.add(new User("A",15));
		users.add(new User("b",19));
		users.add(new User("c",17));
		users.add(new User("a",22));
		
		System.out.println("排序前:");
		print(users);
		
		System.out.println();
		System.out.println();
		
		System.out.println("排序后:");
		Collections.sort(users);
		print(users);
		
		User[] users2 = new User[]{
				new User("a",12),
				new User("C",25),
				new User("B",12),
				new User("A",15),
				new User("b",19),
				new User("c",17),
				new User("a",22)
		};
		
		System.out.println("排序前:");
		print(users2);
		
		System.out.println();
		System.out.println();
		
		System.out.println("排序后:");
		Arrays.sort(users2);
		print(users2);
	}

}

 

  小伙伴们想一下,程序运行的结果应该是什么?

  哈哈,结果应该是:

   A 15
   B 12
   C 25
   a 12
   a 22
   b 19
   c 17

 
可能有的小伙伴想的是:
   a 12
   A 15
   a 22
   B 12
   b 19
   c 17
   C 25 
 
嘿嘿,上面的结果,也是我第一次考虑出的结果,程序运行后得到并不一样怎么办?哪里有错呢?看了几遍,感觉命名没错哈?!No, 还是有错,并不是代码有错哦,而是你出错了!
嘿嘿,请小伙伴仔细看User中的compareTo方法:
    在compareTo方法中的第二行:flag = this.getName().compareTo(o.getName()); 这句话就是罪魁祸首,还真是可恶啊!!!该死,嘻嘻!
    有没有小伙伴看出什么的呢?
    好啦,flag = this.getName().compareTo(o.getName());这句话中也有compareTo方法,在api中找到String的compareTo(String)方法,小编发现了一个重大新闻、重大新闻、重大新闻!!!
    重要的事情说三遍:String的compareTo(String)方法中有这个说明:
      按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。
      按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。
      按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。
    这意味着什么呢?意味着:字符串的排序虽是字典顺序排序,但是大小写有分别。A的Unicode值在a的Unicode前面,所以A排在a的前面咯。
    所以这个问题就解决了。
    String的compareTo(String)方法的下面,还有一个让小编看了特兴奋的方法!!!是什么呢?哈哈,是compareToIgnoreCase(String)方法啦。
    从方法的名字就能理解:使用这个方法进行比较字符串时,忽略、忽略、忽略大小写,哈哈!!!
    当然,这只是小编的猜想,具体是什么作用?还是得看实际的结果对吧!测试的结果如下:
User [name=a, age=12]
User [name=A, age=15]
User [name=a, age=22]
User [name=B, age=12]
User [name=b, age=19]
User [name=c, age=17]
User [name=C, age=25]

  是不是和之前的猜想一样呢!哈哈,今天Comparable接口就到这里了,ByeBye!!!

以上是关于java排序问题,comparator接口,求高手的主要内容,如果未能解决你的问题,请参考以下文章

java中Collection,Arrays内元素的排序问题(comparable,comparator接口的应用)

Java中如何对集合排序

java Comparable 和 Comparator接口区别

Java 对自定义的类排序: Comparable接口

请教:JAVA中,comparator接口如何对double型数据进行排序。

java lang(Comparable接口) 和java util(Comparator接口)分析比较