按升序对 ips 列表进行排序
sort a list of ips in ascending order
我有一个 ip 对象列表,它们的 v4 地址是一个字符串。 (ip为十进制)
现在我想以 ip 部分作为搜索关键字对这个列表进行升序排序。
这是我的第一个方法。它可以工作,但它需要四个函数来 return ip 的每个部分。
Comparator<IP> ipComparator =
Comparator
.comparing(IP::getFirstPart)
.thenComparing(IP::getSecondPart)
.thenComparing(IP::getThirdPart)
.thenComparing(IP::getFourthPart);
我想做这样的事情
Comparator<IP> ipComparator =
Comparator
.comparing(IP::getPart(0))
.thenComparing(IP::getPart(1))
.thenComparing(IP::getPart(2))
.thenComparing(IP::getPart(3));
在不为 return ip 的每个部分定义函数的情况下,最简单的实现方法是什么?
如果您将它们表示为像“192.168.2.4”这样的自然字符串,那么它们将无法排序,但是如果您 zero-prefix 每个八位字节都像“192.168.002.004”,那么这些字符串将被排序正如预期的那样。同样,您可以用十六进制表示它们,例如“C0A80204”。密钥是每个八位字节的固定宽度。
或者,您可以将 4 个八位字节表示为一个数字。需要注意的是,如果第一个八位字节是127或更高,那么一个32位的整数会把它当作一个负数,这会影响排序顺序。最简单的解决方案(如果不是最 memory-efficient)是 return 它作为一个 long 值。
这是一种方法。
- 创建一个列表来保存 IP 地址。
List<InetAddress> ips = new ArrayList<>();
然后创建一些进行排序。我正在演示 Inet4Address class 以接受点分四边形或字节数组。然后洗牌。
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);
根据源代码,Inet4Address
的 hashCode
是地址本身。这可以在不使用密钥提取器的情况下用于排序。但据我所知,它没有记录在案,因此不应依赖。所以可以这样做:
- 使用
ByteBuffer
包装从 getAddress()
返回的字节数组并检索 int
值。
- 然后。由于高位可以任意出现在 IP 地址中,因此对排序
应用的两个 ip 进行无符号比较
ips.sort(Comparator.comparing(ip->
ByteBuffer.wrap(ip.getAddress()).getInt(),
(i1, i2) -> Integer.compareUnsigned(i1, i2)));
现在打印结果。
ips.forEach(ip->System.out.println(ip.getHostAddress()));
打印
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
我有一个 ip 对象列表,它们的 v4 地址是一个字符串。 (ip为十进制)
现在我想以 ip 部分作为搜索关键字对这个列表进行升序排序。
这是我的第一个方法。它可以工作,但它需要四个函数来 return ip 的每个部分。
Comparator<IP> ipComparator =
Comparator
.comparing(IP::getFirstPart)
.thenComparing(IP::getSecondPart)
.thenComparing(IP::getThirdPart)
.thenComparing(IP::getFourthPart);
我想做这样的事情
Comparator<IP> ipComparator =
Comparator
.comparing(IP::getPart(0))
.thenComparing(IP::getPart(1))
.thenComparing(IP::getPart(2))
.thenComparing(IP::getPart(3));
在不为 return ip 的每个部分定义函数的情况下,最简单的实现方法是什么?
如果您将它们表示为像“192.168.2.4”这样的自然字符串,那么它们将无法排序,但是如果您 zero-prefix 每个八位字节都像“192.168.002.004”,那么这些字符串将被排序正如预期的那样。同样,您可以用十六进制表示它们,例如“C0A80204”。密钥是每个八位字节的固定宽度。
或者,您可以将 4 个八位字节表示为一个数字。需要注意的是,如果第一个八位字节是127或更高,那么一个32位的整数会把它当作一个负数,这会影响排序顺序。最简单的解决方案(如果不是最 memory-efficient)是 return 它作为一个 long 值。
这是一种方法。
- 创建一个列表来保存 IP 地址。
List<InetAddress> ips = new ArrayList<>();
然后创建一些进行排序。我正在演示 Inet4Address class 以接受点分四边形或字节数组。然后洗牌。
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);
根据源代码,Inet4Address
的 hashCode
是地址本身。这可以在不使用密钥提取器的情况下用于排序。但据我所知,它没有记录在案,因此不应依赖。所以可以这样做:
- 使用
ByteBuffer
包装从getAddress()
返回的字节数组并检索int
值。 - 然后。由于高位可以任意出现在 IP 地址中,因此对排序 应用的两个 ip 进行无符号比较
ips.sort(Comparator.comparing(ip->
ByteBuffer.wrap(ip.getAddress()).getInt(),
(i1, i2) -> Integer.compareUnsigned(i1, i2)));
现在打印结果。
ips.forEach(ip->System.out.println(ip.getHostAddress()));
打印
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