I have a list of ip objects that have their v4 address as a String. (ip is in decimal)
Now I want to sort this list in ascending order with the ip parts as search keys.
This was my first approach. It works but it needs four functions to return each part of the ip.
Comparator<IP> ipComparator =
Comparator
.comparing(IP::getFirstPart)
.thenComparing(IP::getSecondPart)
.thenComparing(IP::getThirdPart)
.thenComparing(IP::getFourthPart);
I would like to do something like this
Comparator<IP> ipComparator =
Comparator
.comparing(IP::getPart(0))
.thenComparing(IP::getPart(1))
.thenComparing(IP::getPart(2))
.thenComparing(IP::getPart(3));
What is the easiest way to implement this without defining a function to return each part of the ip?
CodePudding user response:
If you represent them as a natural string like "192.168.2.4", then they won't be sortable, but if you zero-prefix each octet like, "192.168.002.004" then the strings will sort as expected. Similarly, you can represent them in hexadecimal like, "C0A80204". The key is fixed width per octet.
Alternatively, you can represent the 4 octets as a single number. The thing to be careful of is that if the first octet is 127 or higher, then a 32-bit integer will treat it as a negative number, which will affect the sort order. The easiest solution (if not the most memory-efficient) is to return it as a long value.
CodePudding user response:
Here is one way to do it.
- create a list to hold the ip addresses.
List<InetAddress> ips = new ArrayList<>();
Then create some to sort. I am demonstrating the Inet4Address class to accept either a dotted quad or a byte array. Then shuffle the list.
for (int i = 1; i < 23; i = 2) {
ips.add(Inet4Address.getByName("192.168.1." i));
ips.add(Inet4Address.getByAddress(new byte[]{(byte)192, (byte)168,
(byte)1, (byte)(i 1)}));
}
Collections.shuffle(ips);
- This hashCode for
Inet4Address
is the address itself. So do an unsigned compare on that value.
ips.sort((a,b)-> Integer.compareUnsigned(a.hashCode(), b.hashCode()));
and print the results.
ips.forEach(ip->System.out.println(ip.getHostAddress()));
prints
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.6
192.168.1.7
192.168.1.8
192.168.1.9
192.168.1.10
192.168.1.11
192.168.1.12
192.168.1.13
192.168.1.14
192.168.1.15
192.168.1.16
192.168.1.17
192.168.1.18
192.168.1.19
192.168.1.20
192.168.1.21
192.168.1.22