Java Custom Sort Order Round Robin-ish sorting

Tom C :

I am Java developer, but I'm blanking on a good algorithm for a specific type of sort I need to do.

Basically, I am going to get some data returned from a query (up to a few thousand rows). I only care about sorting based on a single column. Ironically, that column will likely already be sorted, but not in the way I need it to be.

It's simply this:

I am getting a list of user IDs, and I need to sort them in such a way that it runs through the whole list and starts over. An simple example is easier than the explanation:

Let's say the data is like this:

A A A A B B C D D

A valid sort order for my purpose would be this:

A B C D A B D A A

Basically, I need each user to "get a turn" before getting back to them. There will likely be an uneven number of users, so any extra can just stack at the end.

Again, I'm do this in Java, but am not locked into an specific data structure at this point, etc.

[Additional info: If it helps, specifically what I'm doing is generating data for a load test and want to minimize the same user login into the app multiple times, so I want my test to loop through all available application users before going back to the start of the list. The data is real data, though, and I cannot guarantee each user will have the same number of activities.]

Thanks! Tom

msg45f :
  1. Group values into a LinkedList type structure by whatever grouping function you would like.

  2. Add them into the final resulting collection by polling each group.

Ex)

Given:

public class MyObject {

    private String name;

    public MyObject(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

A dataset:

List<MyObject> objects = new ArrayList<>();


        objects.addAll( Arrays.asList(
            new MyObject("A"),
            new MyObject("C"),
            new MyObject("A"),
            new MyObject("B"),
            new MyObject("B"),
            new MyObject("B"),
            new MyObject("A"),
            new MyObject("A"),
            new MyObject("C"),
            new MyObject("C"),
            new MyObject("A"),
            new MyObject("C")
        ));

And the function:

public static Queue<MyObject> robin(List<MyObject> objects) {

        if(objects.size() == 0) return new LinkedList<>();

        // Group into queues using the getName method
        Map<String, Queue<MyObject>> map = objects.stream()
                .collect(Collectors.groupingBy(MyObject::getName, Collectors.toCollection(LinkedList::new)));

        boolean remaining = true;
        Deque<MyObject> roundRobin = new LinkedList<MyObject>();

        Set<String> keySet = map.keySet();

        // Round robin structure to collect them into a single collection
        while(remaining) {
            remaining = false;
            for(String key : keySet) {
                MyObject obj = map.get(key).poll();
                if(obj == null) continue;
                roundRobin.add(obj);
                remaining = true;
            }
        }

        // Return result
        return roundRobin;
    }

Resultant ordering:

A B C A B C A B C A C A

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=75894&siteId=1