简体   繁体   中英

Java Comparator for InetSocketAddress

I need to write Comparator for InetSocketAddress so I can use this class in a TreeSet . They need to be comparable by address and port.

The code would look something like this, but the problem is I don't know how to compare addresses and ports by <(-1),>(1),=(0)

TreeSet<InetSocketAddress> _tree = new TreeSet<InetSocketAddress> 
    (new Comparator<InetSocketAddress>() {

    public int compare(InetSocketAddress o1, InetSocketAddress o2) {

        ///?????
        return 0;
    }
});

Edit... the actual question. How to compare InetSocketAddress.

Codes with InetSocketAddress#getHostName comparation is incorrect because when hostname is resolved it can be null. Look at constructor:

public InetSocketAddress(String hostname, int port) {
if (port < 0 || port > 0xFFFF) {
    throw new IllegalArgumentException("port out of range:" + port);
}
if (hostname == null) {
    throw new IllegalArgumentException("hostname can't be null");
}
try {
    addr = InetAddress.getByName(hostname);
} catch(UnknownHostException e) {
    this.hostname = hostname;
    addr = null;
}
this.port = port;
}

The code wchich uses only IP is incorrect too - hostname can be unresolved. This should be quite efficient:

Integer getIp(InetSocketAddress addr) {
    byte[] a = addr.getAddress().getAddress();
    return ((a[0] & 0xff) << 24) | ((a[1] & 0xff) << 16) | ((a[2] & 0xff) << 8) | (a[3] & 0xff);
}

public int compare(InetSocketAddress o1, InetSocketAddress o2) {
    //TODO deal with nulls
    if (o1 == o2) {
        return 0;
    } else if(o1.isUnresolved() || o2.isUnresolved()){
        return o1.toString().compareTo(o2.toString());
    } else {
        int compare = getIp(o1).compareTo(getIp(o2));
        if (compare == 0) {
            compare = Integer.valueOf(o1.getPort()).compareTo(o2.getPort());
        }
        return compare;
    }
}

<(-1),>(1),=(0) is needed for sorting I think you can assume ordering - for example:

public int compare(InetSocketAddress o1, InetSocketAddress o2) {
    //TODO deal with nulls
    if(o1 == o2){
        return 0;
    } else {
        return o1.toString().compareTo(o2.toString());
    }
}

This is not very efficient but it ilustrates the idea. Comparing IP (when avaliable, resolved) can be faster.

Depending on whether you need a particular order, or some kind of resolution, this may be correct:

class ISC implements Comparator<InetSocketAddress>
{

@Override
    public int compare(InetSocketAddress o1, InetSocketAddress o2)
    {
        return o1.toString().compareTo(o2.toString());
    }
}

Try using CompareToBuilder , and pass in getAddress().getHostAddress() and getPort() .

You just need to pick a convention.

eg

  1. choose an arbitrary ordering scheme for IP addresses. It just needs to be consistently applied.

    Obviously the dot notation suggests a natural way of doing this, so you can break down eg 127.0.0.1 into {127, 0, 0, 1} and compare it against another eg {84, 23, 10, 2} to be explicit.

    Another option is to convert the address part to long number and just compare those numbers. This is basic hashing.

  2. choose an arbitrary ordering scheme for port numbers. Seems sensible to just use the numeric semantics and eg treat port 55 as less than port 999 (though as far as IP protocol is concerned, such a semantic view is meaningless.)

pseudo-code:

compare (addr1, addr2)
   if addr1.host > addr2.host return 1;
   else if addr1.host < addr2.host return -1;

   if addr1.port > addr2.port return 1;
   else if addr1.port < addr2.port return -1;

   return 0;

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