我有List<Object>
。每个Object
都有Number
(String
)的性质。我需要根据number
字段字母数字对objects
的list
进行排序。
public class Object{
private String number;
}
数字可以是(例如):
#3772-BOZ-007
#3772-BAZ-02
#31-002
#001
每个数字都以#
开头我已经尝试过了,但失败了:
lstObjects.sort(Comparator.naturalOrder());
您需要实现Comparable<>. compareto方法。
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class Obj implements Comparable<Obj> {
private String number;
public Obj(String number) {
this.number = number;
}
@Override
public int compareTo(Obj o2) {
int i1 = numPart();
int i2 = o2.numPart();
if (i1 == i2)
return number.compareTo(o2.number);
else return i2 - i1;
}
private int numPart() {
int dashPos = number.indexOf('-');
String numPart = number.substring(1,
dashPos == -1 ? number.length() : dashPos);
try {
if (numPart.length() > 0)
return Integer.parseInt(numPart);
} catch (NumberFormatException e) {
//
}
return 0;
}
@Override
public String toString() {
return number;
}
}
让我们测试一下:
class Test {
public static void main(String[] args) {
List<Obj> lstObjects = Arrays.asList(
new Obj("#3772-BOZ-007"),
new Obj("#3772-BAZ-02"),
new Obj("#31-002"),
new Obj("#001"),
new Obj("#19"),
new Obj("#22"),
new Obj("#21"),
new Obj("#6"));
lstObjects.sort(Comparator.naturalOrder());
lstObjects.forEach(System.out::println);
}
}
结果:
#001
#6
#19
#21
#22
#31-002
#3772-BAZ-02
#3772-BOZ-007
Object
是java.lang已经使用的术语。对象,因此作为示例名称相当令人困惑。我假设你写了Obj
来代替这个答案的其余部分。
sort方法采用比较器,比较列表中的元素。比较器是一个oracle,它返回任意两个对象,其中一个是"更早的"。
您的列表由您粘贴的Obj
类的实例组成,它没有定义的自然顺序。
你有两个选择:
让这个类有一个自然的顺序
这样做,使类实现Comparable<Self>
。因此:
public class Obj implements Comparable<Obj> {
private String number;
@Override public int compareTo(Obj other) {
return this.number.compareTo(other.number);
}
}
...
lstObjects.sort(Comparator.naturalOrder()):
提供对数值进行比较的比较器。
这假设你在Object
类中有一个public String getNumber()
方法:
lstObjects.sort(Comparator.comparing(Obj::getNumber));
可以实现Comparable
接口,并在compareTo()
方法中定义排序键和排序机制
的例子:
public class MyObject implements Comparable<MyObject> {
private String number;
public MyObject(String number) {
this.number = number;
}
@Override
public int compareTo(MyObject other) {
return this.number.compareTo(other.number);
}
}
让我们假设,你有一个class
package stack.overflow.atest;
public class Flight {
String number;
public Flight(String number) {
this.number = number;
}
@Override
public String toString() {
return "Flight{" + "number=" + number + '}';
}
}
代码段调用:
public static void main(String[] args) {
List<Flight> list = Stream.of(
"#3772-BOZ-007",
"#3772-BAZ-02",
"#31-002",
"#001"
).map(Flight::new)
.sorted((f1, f2) -> f1.number.compareTo(f2.number))
.collect(Collectors.toList());
System.out.println(list);
}
结果:
[Flight{number=#001}, Flight{number=#31-002}, Flight{number=#3772-BAZ-02}, Flight{number=#3772-BOZ-007}]
对Object
s进行排序
通过传递的Comparator
将groupingBy
的HashMap
-default更改为TreeMap
来获得特定的排序顺序。
不要混淆Object
和java.lang.Object
static Pattern pat = Pattern.compile("(?:#(\d+))?(.*)?");
ArrayList<Object> list = new ArrayList<>();
Stream.of(
new Object("#3772-BOZ-007"),
new Object("#3772-BAZ-02"),
new Object("#31-002"),
new Object("#001"))
.collect(groupingBy(Object::getNumber,
() -> new TreeMap<String,List<Object>>(new Comparator<String>() {
@Override
public int compare(String num1, String num2) {
Matcher m1 = pat.matcher(num1);
Matcher m2 = pat.matcher(num2);
m1.find();
m2.find();
Integer i1 = m1.group(1) != null ? Integer.parseInt(m1.group(1)) : -1;
Integer i2 = m2.group(1) != null ? Integer.parseInt(m2.group(1)) : -1;
String s1 = m1.groupCount() > 1 ? m1.group(2) : "";
String s2 = m2.groupCount() > 1 ? m2.group(2) : "";
int cmp = i1.compareTo(i2);
return(cmp == 0 ? s1.compareTo(s2) : cmp);
}}), toList())).values()
.forEach(l -> list.addAll(l));
System.out.println(list);
Object
按#number
排序:
[Object{number=#001},
Object{number=#31-002},
Object{number=#3772-BAZ-02},
Object{number=#3772-BOZ-007}]