Collections.sort () не работает с классом, который реализует Comparable или при использовании Comparator Java - PullRequest
0 голосов
/ 18 ноября 2018

Итак, насколько я могу судить, я правильно реализовал метод CompareTo в своем классе, но когда вызывается Collections.sort (), список не сортируется.Я попытался устранить неполадки с помощью ArrayList, чтобы убедиться, что я все правильно реализую, но безуспешно.У меня тоже нет успеха с компараторами.Пожалуйста, ради бога, кто-нибудь, помогите мне !!

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

Main

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 голосов
/ 18 ноября 2018

Только 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

------------------------------
0 голосов
/ 18 ноября 2018

Вы должны добавить свой компаратор в ArrayList:

 Collections.sort(payments, new NameCompare());
0 голосов
/ 18 ноября 2018

Определенные вами компараторы / сопоставимые переопределения основаны на реализации String # compareTo.Согласно исходной документации метод CompareTo для String возвращает положительное число, отрицательное число или ноль на основе лексикографического порядка.Отрицательное число не обязательно -1 , как вы, кажется, проверяете в своем коде.Таким образом, даже если строка может предшествовать другой лексикографически, ваш код будет упорядочивать ее, только если возвращаемое значение String # compareTo равно -1 (а не если это любое другое отрицательное значение).

Попробуйте использовать следующий код:

@Override public int compareTo(CreditCard o) { 
    return this.getPAN().compareTo(o.getPAN());
 }
0 голосов
/ 18 ноября 2018

Вы должны использовать Collections.sort(list), а не list.sort(null).

Если вы посмотрите на документ для list.sort () , вы увидите, что он сортирует с помощью прилагаемого компаратора.Вы предоставляете null, что (я полагаю) приводит к тому, что ваш список остается не отсортированным.

Collections.sort () , с другой стороны, отсортирует список в соответствии сестественное упорядочение его элементов (как определено вашей реализацией Comparable).

Ваша реализация CreditCard.compareTo() может быть упрощена как:

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

В настоящее время вы используете оба compareTo()и compareToIgnoreCase().Выберите один.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...