简体   繁体   中英

How to maintain an Ordered Linked List and add, remove elements in java

I want to maintain a list of objects called 'ClientStatus' that contain nothing but client identification (id) and some time field ie related to this client. This list should be sorted in terms of this time field in increasing order. The operations I want to support are :

* peek and remove an entry from the beginning 
* Search the list for an entry and if found, remove it
* Add an entry to this list

I expect every new entry to have time >= the last entry in the list but there is a possibility of race condition where I might get out of order values. SO I figured that iterating over the list from the end will be the most time-efficient solution.

These are the DS I used:

  • LinkedList and ListIterator as ListIterator allows you to iterate over the elements from the end and add new entries while iteration. But the code looks messy:

    Say my list has values: 2 3 6 7 9 and I want to add 5

     ListIterator<Integer> it = list.listIterator(list.size()); while (it.hasPrevious()) { if (it.previous().intValue() <= 5) { it.next(); break; } } 

    Is there a better way to do this?

  • I also tried using LinkedList and Dequeue but the descending iterator doesn't let you add/remove entries. I tried to count indices but then set(index, value) replaces existing entry. How do I insert an entry in the list?

====================== Revision 2 ============================

As per the consensus I decided to use a SortedSet, I'll appreciate if the code I wrote can be reviewed for technicalities in consistency between Comparator and equals.

private static class ClientStatus {
    public long id;
    public long time;

    public ClientStatus(final long id, final long time) {
        this.id = id;
        this.time = time;
    }

    @Override
    public boolean equals(final Object o) {
        if ((o == null) || (getClass() != o.getClass())) {
            return false;
        }
        if (this == o) {
            return true;
        }
        ClientStatus obj = (ClientStatus) o;
        return this.id == obj.id;
    }
}

public static void main(String[] args) {

    SortedSet<ClientStatus> active_client_set = new TreeSet<ClientStatus>(
            new Comparator<ClientStatus>() {
                @Override
                public int compare(final ClientStatus o1, final ClientStatus o2) {
                    if (o1.getClass() != o2.getClass()) {
                        return -1;
                    }

                    if (o1 == o2 || o1.id == o2.id) {
                        return 0;
                    }
                    return (o1.time - o2.time) < 0 ? -1 : +1;
                }
            }
    );
}

I'm comparing the id's only one client id can't have multiple entries in the list, but two different clients can have the same time value. This code doesn't seem to work, addition works just fine but if I'm unable to remove an entry based on clientid only.

I think the type you are looking for is a SortedSet which can be implemented by TreeSet .

The sorted set keeps all the entries in the set sorted by using their compare(...) implementation.

All the elements in the set must implement the Comparator<T> interface in order for the SortedSet to work properly.

You might prefer to use SortedMap which works in a similar way. You can set the client id as the value and the time field as the key, and the map will keep the sorting using the time field comparison.

You were also talking about race conditions. The javadoc for using TreeMap discusses this and mentioning that the map must be synchronized externally by using Collections.synchronizedSortedMap(...) .

I haven't tried the synchronized implementation so I can't add much about it.

Check out the docs for more info:

http://docs.oracle.com/javase/7/docs/api/java/util/SortedSet.html http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html

I expect every new entry to have time >= the last entry in the list but there is a possibility of race condition where I might get out of order values. SO I figured that iterating over the list from the end will be the most time-efficient solution.

If you have the possibility of concurrent access, you MUST synchronize iteration and mutation of a LinkedList. You will not just get items out of order, your best case scenario is that the iteration causes a ConcurrentModificationException, the worst case is the indeterminate loss of data.

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