public static List<Set<SrvRecord>> prioritize(final Collection<SrvRecord> records)
    {
        final List<Set<SrvRecord>> result = new LinkedList<>();

        // sort by priority (ascending)
        SortedMap<Integer, Set<SrvRecord>> byPriority = new TreeMap<>();
        for(final SrvRecord record : records) {
            if (byPriority.containsKey(record.getPriority())) {
                byPriority.get(record.getPriority()).add(record);
            } else {
                final Set<SrvRecord> set = new HashSet<>();
                set.add(record);
                byPriority.put(record.getPriority(), set);
            }
        }

        // now, randomize each priority set by weight.
        for(Map.Entry<Integer, Set<SrvRecord>> weights : byPriority.entrySet()) {

            final List<SrvRecord> zeroWeights = new LinkedList<>();
            final Set<SrvRecord> priorityGroupResults = new LinkedHashSet<>(); // A set that retains order (which we'll randomize)

            int totalWeight = 0;
            final Iterator<SrvRecord> i = weights.getValue().iterator();
            while (i.hasNext()) {
                final SrvRecord next = i.next();
                if (next.getWeight() == 0) {
                    // set aside, as these should be considered last according to the RFC.
                    zeroWeights.add(next);
                    i.remove();
                    continue;
                }

                totalWeight += next.getWeight();
            }

            int iterationWeight = totalWeight;
            Iterator<SrvRecord> iter = weights.getValue().iterator();
            while (iter.hasNext()) {
                int needle = new Random().nextInt(iterationWeight);

                while (true) {
                    final SrvRecord record = iter.next();
                    needle -= record.getWeight();
                    if (needle <= 0) {
                        priorityGroupResults.add(record);
                        iter.remove();
                        iterationWeight -= record.getWeight();
                        break;
                    }
                }
                iter = weights.getValue().iterator();
            }

            // Append the hosts with zero priority (shuffled)
            Collections.shuffle(zeroWeights);
            priorityGroupResults.addAll(zeroWeights);

            // Finally, add the entire priority group to the larger result.
            result.add(priorityGroupResults);
        }

        return result;
    }
A (partial) representation of an SRV record, containing an (unresolved) hostname, port, priority and weight attributes.
It is expected to be used primarily to represent the result of an SRV query.

This representation does not include other attributes of an SRV record, such as the service name, transport protocol
and time-to-live.

An indicator is included that signals if the address is to be used with DirectTLS (as opposed to STARTTLS) encryption.
This value can be thought of as being a derivative of the 'service' that was looked up, as for example, a lookup
result for 'xmpp-server' would not be DirectTLS, as opposed to a lookup result for 'xmpps-server', that would be
DirectTLS

@author Guus der Kinderen, guus@goodbytes.nl
xmppserver/src/main/java/org/jivesoftware/openfire/net/SrvRecord.java