Comment trier une liste en utilisant reduce en java 8?


J'ai une liste d'objets List<BoM> dans la nomenclature J'ai un List<BoMLine>, maintenant je dois trier la liste BoM par l'une des propriétés BoMLine en utilisant reduce et retourner une liste triée dans une méthode,

public static List<BoM> sortBoms() {
    List<BoM> sortedBomList = new ArrayList<>();
    BoM bomn = new BoM();
    sortedBomList.add(bomList.parallelStream().reduce(bomn,
            (bom1, bom2) -> sortBoM(bom1, bom2)));
    System.out.println(sortedBomList.size());
    return sortedBomList;
}

BomList est une liste de nomenclatures, et la méthode sortBoM:

private static BoM sortBoM(BoM bom1, BoM bom2) {
    bom2.getLine().stream()
            .sorted((l1, l2) -> l1.getLineNum().compareTo(l2.getLineNum()));
    bom1 = bom2;
    return bom1;
}

Classe de nomenclature:

public class BoM implements Domain {

private String BomCode;
private List<BoMLine> line = new ArrayList<BoMLine>();

public String getBomCode() {
    return BomCode;
}

public void setBomCode(String bomCode) {
    BomCode = bomCode;
}

public List<BoMLine> getLine() {
    return line;
}

public void setLine(List<BoMLine> line) {
    this.line = line;
}

public void addLine(BoMLine bomLine) {
    bomLine.setbOM(this);
    line.add(bomLine);
}}

Et la classe BoMLine:

public class BoMLine implements Domain {

private Long lineNum;
private String material;
private BigDecimal Qty;
private BoM bOM;

public Long getLineNum() {
    return lineNum;
}

public void setLineNum(Long lineNum) {
    this.lineNum = lineNum;
}

public String getMaterial() {
    return material;
}

public void setMaterial(String material) {
    this.material = material;
}

public BigDecimal getQty() {
    return Qty;
}

public void setQty(BigDecimal qty) {
    Qty = qty;
}

public BoM getbOM() {
    return bOM;
}

public void setbOM(BoM bOM) {
    this.bOM = bOM;
}

public String getBoMCode() {
    return bOM.getBomCode();
}

@Override
public String toString() {
    return "BoMLine [ bOM=" + bOM.getBomCode() + ", lineNum=" + lineNum
            + ", material=" + material + ", Qty=" + Qty + "]";
}}

Je dois commander la liste des nomenclatures par BoMLine lineNum. mais il renvoie juste un objet de bomList.Toute aide?

Author: Tunaki, 2015-11-03

3 answers

Vous pouvez trier chaque BoMLine dans l'ordre croissant du numéro de ligne en créant un Comparator personnalisé en utilisant Comparator.comparing:

List<BoM> sortedBomList = new ArrayList<>();
sortedBomList.forEach(bom -> bom.getLine().sort(comparing(BoMLine::getLineNum)));

Notez que cela va muter les List<BoMLine> et List<BoM>, ce qui pourrait ne pas être une bonne idée.

Une meilleure façon serait d'aller pour l'immuabilité et de créer un constructeur prenant la nomenclature de code et nomenclature ligne liste:

List<BoM> sortedBomList = 
        bomList.stream()
               .map(bom -> new BoM(
                               bom.BomCode,
                               bom.getLine().stream()
                                            .sorted(comparing(BoMLine::getLineNum))
                                            .collect(toList())
                           )
               )
               .collect(toList());
 2
Author: Tunaki, 2015-11-03 09:03:51

Vous ne seriez pas en mesure d'obtenir une liste triée avec reduce. Pour récupérer une liste triée, vous devez utiliser la méthode tried in sortBoms () suivie d'une logique de collecte qui renvoie une liste.

Le code modifié ressemblerait à l'extrait ci-dessous:

sortedBomList.add(bomList.parallelStream().sorted(byBoMLineProperty).collect(Collectors.toList());

Cela impliquerait également l'implémentation de byBoMLineProperty comparator qui compare deux nomenclatures par sa propriété BoMLine.

 0
Author: Sendhilkumar Alalasundaram, 2015-11-03 09:07:22

Vous avez considérablement compliqué votre question en publiant beaucoup de code non pertinent. Ce que vous demandez, c'est comment trier une liste de nombres en utilisant reduce, de sorte que tout le problème peut être efficacement simplifié pour implémenter la méthode List<Integer> sorted(List<Integer> list).

Veuillez noter que bien que cela soit possible, il est inefficace et la solution montrée par Tunaki est recommandée. Je suppose que cela fait partie d'une mission universitaire.

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;

import static java.util.Arrays.asList;
import static java.util.Collections.singleton;
import static junit.framework.Assert.assertEquals;

public class ReductionSortingTest {

    @Test
    public void sortsTheList() {
        List<Integer> list =     asList(5,  3, 9, 8, 15, -4, 9);
        List<Integer> expected = asList(-4, 3, 5, 8, 9,  9,  15);

        List<Integer> sorted = sorted(list);

        assertEquals(expected, sorted);
    }

    private static List<Integer> sorted(List<Integer> list) {
        PriorityQueue<Integer> pq = list.stream()
                .map((Integer n) -> new PriorityQueue<>(singleton(n)))
                .reduce(new PriorityQueue<>(), (pq1, pq2) -> {
                    pq1.addAll(pq2);
                    return pq1;
                });

        List<Integer> result = new ArrayList<>();
        while (!pq.isEmpty()) {
            result.add(pq.poll());
        }
        return result;
    }

}

Java manque d'une liste triée j'ai donc décidé d'aller avec PriorityQueue, lire plus à ce sujet dans cette question. PriorityQueue garantit que l'élément supérieur (accessible via le peek(), poll() méthodes est la plus faible selon l'ordre naturel des éléments. L'ordre des éléments retournés par son itérateur n'est pas garanti, d'où la raison pour laquelle nous devons vider la file d'attente en utilisant la méthode poll() - vous voudrez peut-être implémenter votre propre classe SortedList à la place.

MODIFIER:

Voici une solution de liste triée. Gardez à l'esprit que bien qu'il n'y ait pas d'itération finale et il utilise la recherche binaire, son efficacité est loin d'être un simple tri (nous parlons probablement de O(n^3)).

private List<Integer> sorted(List<Integer> list) {
    return list.stream()
            .map(SortedIntList::new)
            .reduce(new SortedIntList(), (a, b) -> {
                a.addAll(b);
                return a;
            });
}

private static class SortedIntList extends ArrayList<Integer> {

    public SortedIntList() {}

    public SortedIntList(int element) {
        super(singletonList(element));
    }

    @Override
    public boolean add(Integer integer) {
        int insertionPoint = Collections.binarySearch(this, integer);
        if (insertionPoint < 0) {
            insertionPoint = -insertionPoint - 1;
        }
        super.add(insertionPoint, integer);
        return true;
    }

    @Override
    public boolean addAll(Collection<? extends Integer> c) {
        c.forEach(this::add);
        return true;
    }

}
 -2
Author: Jaroslaw Pawlak, 2017-05-23 11:51:57