![](/img/trans.png)
[英]Collections.sort() works with Comparable or Comparator?
[英]Collections.sort() not working with class that implements Comparable or when using Comparator Java
据我所知,我已经在类中正确实现了compareTo方法,但是当调用Collections.sort()时,列表似乎没有得到排序。 我尝试使用ArrayList进行故障排除,以确保我正确实施了所有方法,但未成功。 我在Comparators上也没有成功。 拜托,为了上帝的爱,有人来帮助我!
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CreditCard implements Comparable<CreditCard>, Serializable {
//data fields
private String lastName, firstName, PAN;
private Date expDate;
//use of SimpleDateFormat to convert strings/dates
private String pattern = "MM/yy";
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
//Constructor
public CreditCard(String firstName, String lastName, String PAN, String date) {
this.lastName = lastName;
this.firstName = firstName;
this.PAN = PAN;
try {
this.expDate = simpleDateFormat.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
//Getters
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
public String getPAN() {
return PAN;
}
public Date getExpDate() {
return expDate;
}
//Overridden methods
@Override
public String toString() {
return String.format("Name on Card: %s %s\nCard #: %s\nExp Date: %s\n",
firstName,lastName,PAN,simpleDateFormat.format(expDate));
}
@Override
public int compareTo(CreditCard o) {
if (this.getPAN().compareTo(o.getPAN()) == -1) {
return -1;
} else if (this.getPAN().compareToIgnoreCase(o.getPAN()) == 0) {
return 0;
} else {
return 1;
}
}
}
比较
import java.io.Serializable;
import java.util.Comparator;
public class DateCompare implements Comparator<CreditCard>, Serializable{
@Override
public int compare(CreditCard o1, CreditCard o2) {
if (o1.getExpDate().compareTo(o2.getExpDate()) == -1) {
return -1;
} else if ((o1.getExpDate().compareTo(o2.getExpDate()) == 0)) {
return 0;
} else {
return 1;
}
}
}
import java.io.Serializable;
import java.util.Comparator;
public class NameCompare implements Comparator<CreditCard>, Serializable {
@Override
public int compare(CreditCard o1, CreditCard o2) {
if (o1.getLastName().compareToIgnoreCase(o2.getLastName()) == 0) {
if (o1.getFirstName().compareToIgnoreCase(o2.getFirstName()) == 0) {
return 0;
} else if (o1.getFirstName().compareToIgnoreCase(o2.getFirstName()) == -1) {
return -1;
} else {
return 1;
}
} else if (o1.getLastName().compareToIgnoreCase(o2.getLastName()) == -1) {
return -1;
} else {
return 1;
}
}
}
主要
import java.util.ArrayList;
public class CreditPayments {
//instantiate an ArrayList to hold credit cards
private ArrayList<CreditCard> list = new ArrayList<>();
//add credit cards to the list of cards
public void add(CreditCard creditCard) {
list.add(creditCard);
}
//reset the list of credit cards
public void reset() {
list.clear();
}
//Sort and print by PAN
public ArrayList<CreditCard> printByPAN() {
Collections.sort(list);
for (CreditCard cc: list) {
System.out.println(cc);
}
return list;
}
//Sort and print by Name
public ArrayList<CreditCard> printByName() {
Collections.sort(list, new NameCompare());
for (CreditCard cc: list) {
System.out.println(cc);
}
return list;
}
//Sort and print by expiration date
public ArrayList<CreditCard> printByDate() {
Collections.sort(list, new DateCompare());
for (CreditCard cc: list) {
System.out.println(cc);
}
return list;}
public static void main(String[] args) {
ArrayList<CreditCard> payments = new ArrayList<>();
payments.add( new CreditCard("bob", "smith", "1234567890", "03/17") );
payments.add( new CreditCard("bill", "smith", "9999999999", "04/18") );
payments.add( new CreditCard("bob", "smyth", "1111111111", "05/19") );
Collections.sort(payments);
for (CreditCard s: payments) {
System.out.println(s);
}
}
}
您应该使用Collections.sort(list)
而不是list.sort(null)
。
如果查看list.sort()的doco,您会发现它使用提供的比较器进行排序。 您提供的null
(我认为)具有使您的列表不排序的效果。
另一方面, Collections.sort()将根据列表元素的自然顺序对列表进行排序(由您的Comparable
实现指定)。
您的CreditCard.compareTo()
实现可以简化为:
@Override
public int compareTo(CreditCard o) {
return this.PAN.compareTo(o.PAN);
}
当前,您同时使用compareTo()
和compareToIgnoreCase()
。 选一个。
您应该将比较器添加到ArrayList中:
Collections.sort(payments, new NameCompare());
您定义的比较器/可比较替代基于String#compareTo实现。 根据原始文档 ,基于字典顺序,String上的compareTo方法返回正数, 负数或零。 如您似乎正在检查代码,负数不一定是-1 。 因此,即使一个字符串可能在字典上位于另一个字符串的前面,您的代码也只会在String#compareTo的返回值为-1时对它进行排序(如果它是任何其他负值,则不会)。
尝试使用以下代码:
@Override public int compareTo(CreditCard o) {
return this.getPAN().compareTo(o.getPAN());
}
仅getByPAN无法正确排序。 为了使其正确排序,您需要添加一个新的Comparator
。 添加更新的代码和输出。
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
public class CreditPayments {
//instantiate an ArrayList to hold credit cards
private ArrayList<CreditCard> list = new ArrayList<>();
//add credit cards to the list of cards
public void add(CreditCard creditCard) {
list.add(creditCard);
}
//reset the list of credit cards
public void reset() {
list.clear();
}
//Sort and print by PAN
public ArrayList<CreditCard> printByPAN() {
Collections.sort(list, new PanCompare());
for (CreditCard cc: list) {
System.out.println(cc);
}
return list;
}
//Sort and print by Name
public ArrayList<CreditCard> printByName() {
Collections.sort(list, new NameCompare());
for (CreditCard cc: list) {
System.out.println(cc);
}
return list;
}
//Sort and print by expiration date
public ArrayList<CreditCard> printByDate() {
Collections.sort(list, new DateCompare());
for (CreditCard cc: list) {
System.out.println(cc);
}
return list;}
public static void main(String[] args) {
ArrayList<CreditCard> payments = new ArrayList<>();
payments.add( new CreditCard("bob", "smith", "1234567890", "03/17") );
payments.add( new CreditCard("bill", "smith", "9999999999", "04/18") );
payments.add( new CreditCard("bob", "smyth", "1111111111", "05/19") );
CreditPayments s = new CreditPayments();
s.list = payments;
System.out.println("print by name");
s.printByName();
System.out.println("------------------------------");
System.out.println("print by date");
s.printByDate();
System.out.println("------------------------------");
System.out.println("print by pan");
s.printByPAN();
System.out.println("------------------------------");
}
}
class CreditCard implements Comparable<CreditCard>, Serializable {
//data fields
private String lastName, firstName, PAN;
private Date expDate;
//use of SimpleDateFormat to convert strings/dates
private String pattern = "MM/yy";
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
//Constructor
public CreditCard(String firstName, String lastName, String PAN, String date) {
this.lastName = lastName;
this.firstName = firstName;
this.PAN = PAN;
try {
this.expDate = simpleDateFormat.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
//Getters
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
public String getPAN() {
return PAN;
}
public Date getExpDate() {
return expDate;
}
//Overridden methods
@Override
public String toString() {
return String.format("Name on Card: %s %s\nCard #: %s\nExp Date: %s\n",
firstName,lastName,PAN,simpleDateFormat.format(expDate));
}
@Override
public int compareTo(CreditCard o) {
if (this.getPAN().compareTo(o.getPAN()) == -1) {
return -1;
} else if (this.getPAN().compareToIgnoreCase(o.getPAN()) == 0) {
return 0;
} else {
return 1;
}
}
}
class DateCompare implements Comparator<CreditCard>, Serializable {
@Override
public int compare(CreditCard o1, CreditCard o2) {
if (o1.getExpDate().compareTo(o2.getExpDate()) == -1) {
return -1;
} else if ((o1.getExpDate().compareTo(o2.getExpDate()) == 0)) {
return 0;
} else {
return 1;
}
}
}
class NameCompare implements Comparator<CreditCard>, Serializable {
@Override
public int compare(CreditCard o1, CreditCard o2) {
if (o1.getLastName().compareToIgnoreCase(o2.getLastName()) == 0) {
if (o1.getFirstName().compareToIgnoreCase(o2.getFirstName()) == 0) {
return 0;
} else if (o1.getFirstName().compareToIgnoreCase(o2.getFirstName()) == -1) {
return -1;
} else {
return 1;
}
} else if (o1.getLastName().compareToIgnoreCase(o2.getLastName()) == -1) {
return -1;
} else {
return 1;
}
}
}
class PanCompare implements Comparator<CreditCard>, Serializable {
@Override
public int compare(CreditCard o1, CreditCard o2) {
return o1.getPAN().compareTo(o2.getPAN());
}
}
输出,
print by name
Name on Card: bob smith
Card #: 1234567890
Exp Date: 03/17
Name on Card: bill smith
Card #: 9999999999
Exp Date: 04/18
Name on Card: bob smyth
Card #: 1111111111
Exp Date: 05/19
------------------------------
print by date
Name on Card: bob smith
Card #: 1234567890
Exp Date: 03/17
Name on Card: bill smith
Card #: 9999999999
Exp Date: 04/18
Name on Card: bob smyth
Card #: 1111111111
Exp Date: 05/19
------------------------------
print by pan
Name on Card: bob smyth
Card #: 1111111111
Exp Date: 05/19
Name on Card: bob smith
Card #: 1234567890
Exp Date: 03/17
Name on Card: bill smith
Card #: 9999999999
Exp Date: 04/18
------------------------------
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.