Collections.sort()无法与实现Comparable的类一起使用,或在使用Comparator Java时使用

时间:2018-11-18 04:56:51

标签: java generics interface

据我所知,我已经在类中正确实现了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);
        }
        }
}

4 个答案:

答案 0 :(得分:2)

您应该使用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()。选择一个。

答案 1 :(得分:1)

您应该将比较器添加到ArrayList:

 Collections.sort(payments, new NameCompare());

答案 2 :(得分:0)

您定义的比较器/可比较替代基于String#compareTo实现。根据{{​​3}},String的compareTo方法根据字典顺序返回正数,负数或零。负数似乎是不一定是,因为您似乎正在检查代码。因此,即使一个字符串可能在字典上位于另一个字符串的前面,您的代码也只会在String#compareTo的返回值为-1(而不是其他任何负值的情况)时对它进行排序。

尝试使用以下代码:

@Override public int compareTo(CreditCard o) { 
    return this.getPAN().compareTo(o.getPAN());
 }

答案 3 :(得分:0)

只有getByPAN不能正确排序。为了使其正确排序,您需要添加一个新的SampleEmbeddingHelper。添加更新的代码和输出。

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());
    }
}