1

I have list of objects:

{
  "rn": "14",
  "time": "2020-06-16 16:47:55",
  "id": 42332392988,
  "termname": "S1160AFB",
  "type": "100",
  "trancode": "110",
  "pan": "4790729949581839",
  "amount": "360.96",
  "approvalcode": "44444"
},
{
  "rn": "15",
  "time": "2020-06-16 16:48:55",
  "id": 42330308379,
  "termname": "S1160AFB",
  "type": "100",
  "trancode": "110",
  "pan": "4149510064617121",
  "amount": "360.96",
  "approvalcode": "55555"
},
{
  "rn": "13",
  "time": "2020-06-16 16:49:11",
  "id": 42332530886,
  "termname": "S1160AFB",
  "type": "420",
  "trancode": "110",
  "pan": "4790729949581839",
  "amount": "360.96",
  "approvalcode": "44444"
}

I need delete from list objects if :

  1. they have the same field approvalcode. (approvalcode - unique. And can not be more than two identical)
  2. Of two objects with the same approvalcode, you need to check the one in which the date is greater and and if in this object type = 420. Delete both objects from list.

I decided it like this:

  1. I sort list by approvalcode and date.

     List<Transaction> filteredTrans = transResponse.getTransaction().stream().sorted(Comparator.comparing(Transaction::approvalcode).thenComparing(Transaction::getTime))
     .collect(Collectors.toList());
    

After sorting, i compare the two closest objects.

  for (int i=0; i<filteredTrans.size()-1; i++) {
  if (filteredTrans.get(i).getApprovalcode().equals(filteredTrans.get(j).getApprovalcode()) && filteredTrans.get(j).getType().equals("420")) {
      filteredTrans.remove(i);
      filteredTrans.remove(j);
      j++;
  }
}

But I do not like the second part of the code. Can you please advise how it be improved?

Lukas
  • 141
  • 6

2 Answers2

1

You should use a map instead of sorting. Here's how you can proceed with this

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Test {
  static class Transaction {
    String approvalCode;
    LocalDateTime time;
    int type;

    public Transaction(String approvalCode, LocalDateTime time, int type) {
      this.approvalCode = approvalCode;
      this.time = time;
      this.type = type;
    }

    public int getType() {
      return type;
    }

    public LocalDateTime getTime() {
      return time;
    }

    public String getApprovalCode() {
      return approvalCode;
    }

      @Override
      public String toString() {
          return "Transaction{" +
                  "approvalCode='" + approvalCode + '\'' +
                  ", time=" + time +
                  ", type=" + type +
                  '}';
      }
  }

  public static void main(String[] args) {
    List<Transaction> transactions = new ArrayList<>();
    transactions.add(new Transaction("1", LocalDateTime.now(), 420));
    transactions.add(new Transaction("1", LocalDateTime.now(), 11));
    transactions.add(new Transaction("1", LocalDateTime.now(), 12));
    transactions.add(new Transaction("2", LocalDateTime.now(), 13));
    transactions.add(new Transaction("2", LocalDateTime.now(), 14));
    transactions.add(new Transaction("2", LocalDateTime.now(), 420));
    System.out.println(
        transactions.stream()
            .collect(
                Collectors.toMap(
                    Transaction::getApprovalCode,
                    Function.identity(),
                    (u, v) -> u.getTime().compareTo(v.getTime()) > 0 ? u : v))
            .values()
            .stream()
            .filter(v -> v.getType() != 420)
            .collect(Collectors.toList()));
  }
}

When iterating through a list, do not delete from the same list. It can lead to concurrent modification exception. Instead, copy all required elements to a new list/use stream filter

Palash Goel
  • 624
  • 6
  • 17
  • Thx for answer, but i need delete both objects if equals approvalCode and if in that where the date is greate type = 420. For example: List transactions = new ArrayList<>(); transactions.add(new Transaction("1", LocalDateTime.now(), 420)); transactions.add(new Transaction("1", LocalDateTime.now(), 12)); transactions.add(new Transaction("2", LocalDateTime.now(), 13)); From this should stay Transaction with approvalCode == 2. – Lukas Jun 29 '20 at 08:30
  • Result: [Transaction{approvalCode='1', time=2020-06-29T02:48:15.828, type=12}] This will delete Transaction with approvalCode=2. Isn't this what you mean? – Palash Goel Jun 29 '20 at 09:37
  • approvalCode=2 had to stay.Sorry if I poorly formulate the question – Lukas Jun 29 '20 at 13:35
  • >2. Of two objects with the same approvalcode, you need to check the one in which the date is greater and and if in this object type = 420. Delete both objects from list. Answered with the given conditions. – Palash Goel Jun 29 '20 at 14:22
  • Yes, but object with the same approvalcode may be a maximum of 2. Sorry, Didn’t write it right away – Lukas Jun 29 '20 at 15:38
  • The answer still remains the same. It does not matter if there are 2 or 100 objects with the same approvalcode. I can only help if you clearly define what is the expected output. – Palash Goel Jun 29 '20 at 16:36
  • For example: List transactions = new ArrayList<>(); transactions.add(new Transaction("1", LocalDateTime.now(), 420)); transactions.add(new Transaction("1", LocalDateTime.now(), 12)); transactions.add(new Transaction("2", LocalDateTime.now(), 13)); From this should stay 1 object where Transaction with approvalCode == 2 – Lukas Jun 29 '20 at 16:40
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/216893/discussion-between-palash-goel-and-lukas). – Palash Goel Jun 29 '20 at 16:49
0

Thx for help all. This code help me:

List<Transaction> filteredTrans = transResponse.getTransaction().stream()
    .collect(Collectors.groupingBy(Transaction::getApprovalcode))
    .values()
    .stream()
    .filter(l -> {
        if (l.size() == 1) return true;
        Transaction maxTimeTr = l.stream().max(Comparator.comparing(Transaction::getTime)).orElseThrow();
        return !maxTimeTr.getType().equals("420");
    })
    .flatMap(Collection::stream)
    .collect(Collectors.toList());
Lukas
  • 141
  • 6