Сборщики потока Java8 - разделение списка на основе суммы значений - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь разбить список на несколько подсписков, исходя из условия, что сумма определенного поля должна быть меньше, чем 'x'.Ниже приведен тот же код:

public class TestGrouping {
   public static class Transaction{
     String txnId;
     String comment;
     Amount amount;

    public Transaction(String txnId, String comment, Amount amount) {
        this.txnId = txnId;
        this.comment = comment;
        this.amount = amount;
    }
}

public static class Amount{
     String amountValue;

    public Amount(String amountValue) {
        this.amountValue = amountValue;

    }
}
public static void main(String[] args) {
    List<Transaction> transactionList = new ArrayList<>();
    Transaction txn1 = new Transaction("T1","comment1",new Amount("81"));
    Transaction txn2 = new Transaction("T2","comment2",new Amount("5"));
    Transaction txn3 = new Transaction("T3","comment3",new Amount("12"));
    Transaction txn4 = new Transaction("T4","comment4",new Amount("28"));
    transactionList.add(txn1);
    transactionList.add(txn2);
    transactionList.add(txn3);
    transactionList.add(txn4);

//below is what i thought might work
//    transactionList.stream().collect(groupingBy (r->Collectors.summingInt(Integer.valueOf(r.amount.amountValue)),Collectors.mapping(t -> t, toList())));
}

Цель состоит в том, чтобы разбить транзакцииList на 2 (или более) подсписка - где сумма «сумма» меньше 100. Таким образом, я мог бы иметь подсписок только txn1- имеющий сумму 81;и у другого подсписка есть txn2, txn3, txn4 (поскольку их сумма меньше 100).Другая возможность - иметь sublist1, имеющий txn1, txn2, txn3;и другой подсписок только с txn4.В принципе, не пытаясь создать самые «оптимальные» списки, просто эта сумма должна быть меньше 100.

Какие-нибудь подсказки?

1 Ответ

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

Идея состоит в том, чтобы использовать собственный коллектор для генерации списка пары (сумма, транзакции), этот список должен быть изначально отсортирован.Метод аккумулятора (здесь Accumulator.accept) выполняет логику группировки, я не реализовал объединение, потому что нет необходимости в объединителе в непараллельном потоке.Ниже приведен фрагмент кода, надеюсь, это поможет.

    public class TestStream {

    public class Transaction {
        String txnId;
        String comment;
        Amount amount;

        public Transaction(String txnId, String comment, Amount amount) {
            this.txnId = txnId;
            this.comment = comment;
            this.amount = amount;
        }
    }

    public class Amount {
        String amountValue;

        public Amount(String amountValue) {
            this.amountValue = amountValue;

        }
    }

    @Test
    public void test() {
        List<Transaction> transactionList = new ArrayList<>();
        Transaction txn1 = new Transaction("T1", "comment1", new Amount("81"));
        Transaction txn2 = new Transaction("T2", "comment2", new Amount("5"));
        Transaction txn3 = new Transaction("T3", "comment3", new Amount("12"));
        Transaction txn4 = new Transaction("T4", "comment4", new Amount("28"));
        transactionList.add(txn1);
        transactionList.add(txn2);
        transactionList.add(txn3);
        transactionList.add(txn4);

        transactionList.stream()
            .sorted(Comparator.comparing(tr -> Integer.valueOf(tr.amount.amountValue)))
            .collect(ArrayList<Pair<Integer, List<Transaction>>>::new, Accumulator::accept, (x, y) -> {
            })
            .forEach(t -> {
                System.out.println(t.left);
            });
    }

    static class Accumulator {
        public static void accept(List<Pair<Integer, List<Transaction>>> lPair, Transaction tr) {
            Pair<Integer, List<Transaction>> lastPair = lPair.isEmpty() ? null : lPair.get(lPair.size() - 1);
            Integer amount = Integer.valueOf(tr.amount.amountValue);
            if (Objects.isNull(lastPair) || lastPair.left + amount > 100) {
                lPair.add(
                    new TestStream().new Pair<Integer, List<Transaction>>(amount,
                        Arrays.asList(tr)));
            } else {
                List<Transaction> newList = new ArrayList<>();
                newList.addAll(lastPair.getRight());
                newList.add(tr);
                lastPair.setLeft(lastPair.getLeft() + amount);
                lastPair.setRight(newList);
            }
        }
    }

    class Pair<T, V> {
        private T left;
        private V right;

        /**
         * 
         */
        public Pair(T left, V right) {
            this.left = left;
            this.right = right;
        }

        public V getRight() {
            return right;
        }

        public T getLeft() {
            return left;
        }

        public void setLeft(T left) {
            this.left = left;
        }

        public void setRight(V right) {
            this.right = right;
        }
    }

}
...