Java 8 в Action Streams четкое разъяснение - PullRequest
0 голосов
/ 03 июля 2019

Я проходил упражнения в Java 8 в действии, и я столкнулся с этим вопросом.Существует 2 класса Trader и Transaction, описанные следующим образом:

public class Trader {
    private final String name;
    private final String city;

    public Trader(String n, String c) {
        this.name = n;
        this.city = c;
    }

    public String getName() {
        return this.name;
    }

    public String getCity() {
        return this.city;
    }

    public String toString() {
        return "Trader:" + this.name + " in " + this.city;
    }
}
public class Transaction {
    private final Trader trader;
    private final int year;
    private final int value;

    public Transaction(Trader trader, int year, int value) {
        this.trader = trader;
        this.year = year;
        this.value = value;
    }

    public Trader getTrader() {
        return this.trader;
    }

    public int getYear() {
        return this.year;
    }

    public int getValue() {
        return this.value;
    }

    public String toString() {
        return "{" + this.trader + ", " + "year: " + this.year + ", " + "value:" + this.value + "}";
    }
}

Трейдеры и список транзакций создаются следующим образом:

        Trader mario = new Trader("Mario", "Milan");
        Trader alan = new Trader("Alan", "Cambridge");
        Trader brian = new Trader("Brian", "Cambridge");
        Trader raoul = new Trader("Raoul", "Cambridge");
        List<Transaction> transactions = Arrays.asList(new Transaction(brian, 2011, 300),
                new Transaction(raoul, 2012, 1000), new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710), new Transaction(mario, 2012, 700), new Transaction(alan, 2012, 950));

Вопрос в том, чтобы найти всех трейдеровиз Кембриджа и сортировать их по имени.Решение этой проблемы в книге таково:

List<Trader> traders = transactions.stream()
                               .map(Transaction::getTrader)
                               .filter(trader -> trader.getCity().equals("Cambridge"))
                               .distinct()
                               .sorted(comparing(Trader::getName))
                               .collect(toList());

Ответ, приведенный выше, возвращает правильные результаты, но мне было интересно, как и , почему different () использование поля name для возврата отдельных трейдеров?

Ответы [ 2 ]

4 голосов
/ 03 июля 2019

distinct() не использует поле имени для возврата отдельных трейдеров.Он использует метод equals, чтобы определить, идентичны ли два Trader.Поскольку Trader не переопределяет equals, единственная причина, по которой этот код работает, заключается в том, что он передает один и тот же экземпляр (на который ссылается raoul) двум Transaction s, поэтому реализации equals по умолчанию (которыепроверок ==) достаточно, чтобы определить, что они идентичны.

Следовательно, вывод List:

[Trader:Alan in Cambridge, Trader:Brian in Cambridge, Trader:Raoul in Cambridge]

Однако, если вы сделаете следующее изменение:

Trader mario = new Trader("Mario", "Milan");
Trader alan = new Trader("Alan", "Cambridge");
Trader brian = new Trader("Brian", "Cambridge");
Trader raoul = new Trader("Raoul", "Cambridge");
Trader raoul2 = new Trader("Raoul", "Cambridge");
List<Transaction> transactions = Arrays.asList(new Transaction(brian, 2011, 300),
        new Transaction(raoul, 2012, 1000), new Transaction(raoul2, 2011, 400),
        new Transaction(mario, 2012, 710), new Transaction(mario, 2012, 700), new Transaction(alan, 2012, 950));

Вы увидите, что теперь, поскольку raoul и raoul2 не равны (даже если они имеют одинаковое имя), они оба появятся в выводе List:

[Trader:Alan in Cambridge, Trader:Brian in Cambridge, Trader:Raoul in Cambridge, Trader:Raoul in Cambridge]
1 голос
/ 03 июля 2019

Stream.distinct () сравнивает объекты по Object.equals (Object) https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#distinct--

в этом примере у вас есть 4 объекта Trader, которые сравниваются реализацией по умолчанию Object.equals () , поскольку класс Trades не переопределяет метод equals

...