Java 8 Trier HashMap où la clé de carte est un objet de <String, Integer>

vscoder:

J'ai une simple classe client comme si

public class Customer {
    public int age;
    public int discount;
    public String name;

    public Customer(String name) {
        this.name = name;
    }
    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Customer(String name, int age, int discount) {
        this.name = name;
        this.age = age;
        this.discount = discount;
    }

    @Override
    public String toString() {
        return "Customer [age=" + age + ", discount=" + discount + ", name=" + name + "]";
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Integer getDiscount() {
        return discount;
    }
    public void setDiscount(int discount) {
        this.discount = discount;
    }
}

Je remplir une liste de ces objets en utilisant cette

List<Customer> customerList = new ArrayList<>(Arrays.asList(
        new Customer("John",   2, 15),
        new Customer("John",   4, 15),
        new Customer("John",   6, 25),
        new Customer("Joe",    3, 15),
        new Customer("Joe",    3, 15),
        new Customer("Joe",    3, 15),
        new Customer("Goerge", 6, 25),
        new Customer("Goerge", 6, 25),
        new Customer("Mary",   7, 25),
        new Customer("Jane",   1, 15),
        new Customer("Jane",   2, 15),
        new Customer("Jane",   8, 25),
        new Customer("Jane",   8, 25)
        ));

Maintenant, je veux groupe et compte les noms et les remises, en utilisant un collecteur comme celui-ci

Map<Object, Long> collected = customerList
    .stream()
    .collect(Collectors.groupingBy(x -> Arrays.asList(x.name, x.discount), Collectors.counting()));

Je peux revoir ma sortie en utilisant cette

collected.entrySet().forEach(c -> {
    System.out.println(c);
});

Ce qui produit les éléments suivants

[Jane, 15]=2
[Joe, 15]=3
[John, 15]=2
[Mary, 25]=1
[John, 25]=1
[Jane, 25]=2
[Goerge, 25]=2

La question est de savoir comment puis-je trier la carte par son nom et de réduction de sorte qu'il ressemble à ceci

[Goerge, 25]=2
[Jane, 15]=2
[Jane, 25]=2
[Joe, 15]=3
[John, 15]=2
[John, 25]=1
[Mary, 25]=1

Je continue à se cogner contre le type d'objet qui est retourné par le collecteur?

Puis-je jetai le collecteur afin qu'il retourne une classe, peut-être quelque chose comme

private class DiscountCounts
{
    public String name;
    public Integer discount;
}

Est - il possible de convertir Map<**Object**, Long>()à quelque chose comme Map<DiscountCounts, Long>(), ce serait permettre l' accès aux champs de la clé Carte en utilisant lambda ou des constructions Comparator?

J'ai essayé quelque chose comme ça, itérer sur la carte et convertir manuellement à la carte Je veux, mais je ne peux pas obtenir aux clés de la collection originale?

    Map<DiscountCounts, Long> collected2 = new HashMap<>();
    collected.entrySet().forEach(o -> {
        DiscountCounts key1 = (DiscountCounts)o.getKey();  //--> Fails here
        collected2.put((DiscountCounts)o.getKey(), o.getValue());
    });
Dead Pool :

Une façon vous pouvez le faire sans utiliser la DiscountCountsclasse est, d' abord trier la liste, puis effectuer la tâtonnement par le fonctionnement et l' utilisation LinkedHashMappour enregistrer l'ordre de tri

Map<List<Object>, Long> map = customerList.stream()
                .sorted(Comparator.comparing(Customer::getName).thenComparing(Customer::getDiscount))
                .collect(Collectors.groupingBy(x -> Arrays.asList(x.name, x.discount),LinkedHashMap::new, Collectors.counting()));

L'autre façon en utilisant la DiscountCountsclasse est, par dérogation à la equalset hashcodede la DiscountCountsclasse et faire une création groupingBy DiscountCountsobjet pour chaque Customerobjet comme clé Mapet l' utilisation TreeMapavec Comparatorpour trier le résultat

Map<DiscountCounts, Long> result = customerList.stream().collect(Collectors.groupingBy(
            c -> new DiscountCounts(c.getName(), c.getDiscount()),
            () -> new TreeMap<DiscountCounts, Long>(
                    Comparator.comparing(DiscountCounts::getName).thenComparing(DiscountCounts::getDiscount)),
            Collectors.counting()));

@Andreas Suggest dans le commentaire Enlighten - moi une autre façon de le faire, et je pense que c'est l' un des meilleurs approche que vous pouvez mettre en œuvre Comparablesur DiscountCountset fournir la logique de tri de sorte que vous n'avez pas besoin de fournir à ComparatorTreeMap

@Override
public int compareTo(DiscountCounts cust) {

      int last = this.getName().compareTo(cust.getName());

     return last == 0 ? this.getDiscount().compareTo(cust.getDiscount()) : last;
}

Map<DiscountCounts, Long> result1 = customerList.stream().collect(Collectors.groupingBy(
            c -> new DiscountCounts(c.getName(), c.getDiscount()), TreeMap::new, Collectors.counting()));

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=300709&siteId=1
conseillé
Classement