简体   繁体   中英

How do I merge two sorted object lists based on common attribute in Java

I have two object lists both with a common attribute called timestamp and both are sorted by timestamp.

I want to broadcast these objects one by one based on the timestamp, example if first object of 1st list has timestamp < first object of 2nd list, broadcast first object of the 1st list and then compare second object of the 1st list with the first object of the 2nd list.

I am a newbie in java. This is what I have come up with:

 //Merge the 2 object lists based on timestamp
        ListIterator<x> xIterator = list1.listIterator();
        ListIterator<y> yIterator = list2.listIterator();
        while (xIterator.hasNext() && yIterator.hasNext()) {
            if (xIterator.next().timestamp <= yIterator.next().timestamp) {
                Bundle extra = new Bundle();
                extra.putParcelable(LocalBroadcastConstants.ACTION, xIterator.previous());
                MyBroadcastManager.getInstance(getTargetContext()).sendBroadcast(
                        new Intent(LocalBroadcastConstants.ACTION_SEND).putExtras(extra)
                );
                yIterator.previous();
            } else {
                Bundle extra = new Bundle();
                extra.putParcelable(LocalBroadcastConstants.ACTION,
                        yIterator.previous());
                MyBroadcastManager.getInstance(getTargetContext()).sendBroadcast(
                        new Intent(LocalBroadcastConstants.ACTION_SEND).putExtras(extra)
                );
                xIterator.previous();
            }

I know my logic is incorrect because for the first item in the Iterators, xIterator.previous and yIterator.previous will point to nothing. I can't seem to find the correct solution for this problem statement. Please help.

Use indexes instead of iterator. You can also use methods to prevent code redundancy

int xIndex = 0;
int yIndex = 0;

while (xIndex < list1.size() && yIndex < list2.size()) {
    if (list1[xIndex].timestamp <= list2[yIndex].timestamp) {
        broadcast(list1, xIndex);
        ++xIndex;
    }
    else {
        broadcast(list2, yIndex);
        ++yIndex;
    }
}

dealWithLeftovers(list1, xIndex);
dealWithLeftovers(list2, yIndex);

broadcast :

private void broadcast(List<> list, int index) {
    Bundle extra = new Bundle();
    extra.putParcelable(LocalBroadcastConstants.ACTION, list[index]);
    MyBroadcastManager.getInstance(getTargetContext()).sendBroadcast(
        new Intent(LocalBroadcastConstants.ACTION_SEND).putExtras(extra)
    );
}

dealWithLeftovers :

private void dealWithLeftovers(List<> list, int index) {
    for (int i = index; i < list.size() ; ++i) {
        broadcast(list, i);
    }
}

A simple but easy to implement solution:

  • create a list that simply contains all objects from both lists
  • create a Comparator that knows how to extract timestamps from both different classes - to then compare them
  • use Collections .sort() to sort the merged list using that comparator

That's it. Now you loop the sorted list to broadcast objects in order.

If you want to merge two lists with Sorting with one of the fields, the below example may help u. Using Java8 Streams

Obj p1 = new Obj();
    p1.setDept("EC");
    p1.setName("Sagar");
    p1.setJoinedDate(new Date(2007, 8, 2));

    Obj p2 = new Obj();
    p2.setDept("EE");
    p2.setName("Rang");
    p2.setJoinedDate(new Date(2007, 8, 3));

    Obj p3 = new Obj();
    p3.setDept("ME");
    p3.setName("Avadh");
    p3.setJoinedDate(new Date(2008, 8, 2));

    Obj p4 = new Obj();
    p4.setDept("IP");
    p4.setName("Pams");
    p4.setJoinedDate(new Date(2007, 8, 1));

    List<Obj> dept1 = new ArrayList<>();
    dept1.add(p1);
    dept1.add(p2);

    List<Obj> dept2 = new ArrayList<>();
    dept2.add(p3);
    dept2.add(p4);
    dept1.addAll(dept2);
    List<Obj> sortedList = dept1.stream().sorted(new Comparator<Obj>() {

        @Override
        public int compare(Obj o1, Obj o2) {
            if(Instant.ofEpochMilli(o1.getJoinedDate().getTime()).atZone(ZoneId.systemDefault())
            .toLocalDateTime().isBefore(Instant.ofEpochMilli(o2.getJoinedDate().getTime()).atZone(ZoneId.systemDefault())
            .toLocalDateTime())){
                return -1;
            }else if(Instant.ofEpochMilli(o1.getJoinedDate().getTime()).atZone(ZoneId.systemDefault())
                    .toLocalDateTime().isAfter(Instant.ofEpochMilli(o2.getJoinedDate().getTime()).atZone(ZoneId.systemDefault())
                            .toLocalDateTime())){
                return 1;
            }
            return 0;
        }
    }).collect(Collectors.toList());

    System.out.println(sortedList);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM