Учитывая список IP-адресов, как вы находите мин, макс? - PullRequest
6 голосов
/ 11 мая 2010

В Java у меня есть arrayList IP-адреса. как мне найти мин и макс?

Я использовал Collection.min (), но он не работает в случае, подобном:

192.168.0.1  <--min 
192.168.0.250
192.168.0.9  <--max

как мне вернуть

192.168.0.1  <--min
192.168.0.250 <--max

вместо этого?


ArrayList извлекается из базы данных. Я должен был бы сделать эту операцию за тик (каждый тик с интервалом в 5 секунд). Максимальное количество IP-адресов может составить, вероятно, 300.

Ответы [ 5 ]

13 голосов
/ 11 мая 2010

Преобразовать IP-адрес в длинное целое, а затем отсортировать его. 192.168.0.1 можно преобразовать в целое число с помощью двоичной арифметики / операторов:

( 192 << 24 ) + ( 168 << 16 ) + ( 0 << 8 ) + ( 1 << 0 )

и так далее. Прочитайте комментарии ниже об использовании правильного типа данных.

7 голосов
/ 11 мая 2010

Вы храните IP-адреса как String экземпляры? Вероятно, это так, потому что String отсортированы лексикографически, что означает "10" < "2".

Если вы хотите отсортировать их численно, есть несколько способов:

  • Вместо того, чтобы поместить их в List<String>, поместите их в List<Integer>
    • или, может быть, даже SortedSet<Integer>
  • Сохраните List<String>, но предоставьте собственный компаратор, который преобразует String в числовое значение для сравнения.
    • может быть не самым эффективным, но работает без существенных изменений в существующей инфраструктуре
      • хотя, возможно, серьезные изменения неплохи для начала ...

Вот пример, который объединяет немного обоих в один:

import java.util.*;

public class IPSorter {
    static Long toNumeric(String ip) {
        Scanner sc = new Scanner(ip).useDelimiter("\\.");
        return 
            (sc.nextLong() << 24) + 
            (sc.nextLong() << 16) + 
            (sc.nextLong() << 8) + 
            (sc.nextLong()); 
    }
    public static void main(String[] args) {
        Comparator<String> ipComparator = new Comparator<String>() {
            @Override public int compare(String ip1, String ip2) {
                return toNumeric(ip1).compareTo(toNumeric(ip2));
            }       
        };
        SortedSet<String> ips = new TreeSet<String>(ipComparator);
        ips.addAll(Arrays.asList(
            "192.168.0.1", "192.168.0.250", "192.168.0.9", "9.9.9.9"
        ));
        System.out.println(ips);
        // "[9.9.9.9, 192.168.0.1, 192.168.0.9, 192.168.0.250]"
    }
}

API ссылки

2 голосов
/ 13 июля 2010

Ссылаясь на Java - IP-адрес для целого числа и обратно

public static String intToIp(int i) {
    return ((i >> 24 ) & 0xFF) + "." +
           ((i >> 16 ) & 0xFF) + "." +
           ((i >>  8 ) & 0xFF) + "." +
           ( i        & 0xFF);
}

public static Long ipToInt(String addr) {
    String[] addrArray = addr.split("\\.");

    long num = 0;
    for (int i=0;i<addrArray.length;i++) {
        int power = 3-i;

        num += ((Integer.parseInt(addrArray[i])%256 * Math.pow(256,power)));
    }
    return num;
}

Получив из базы данных строку IP-адреса, я преобразовал все в ArrayList и затем применил Collection.min (). Затем я конвертирую long в int, а затем обратно в String. Чтобы получить отсортированную строку IP-адресов.

Спасибо

2 голосов
/ 11 мая 2010

Если вы рассматриваете IP-адреса как целое число (long), вы можете отсортировать их. Напишите пользовательский компаратор, который может разбить IP-адрес на массив целых, а затем создать общее значение типа int, выполнив следующие действия.

//Split and convert the address into an array of ints...

addressIntValue =  address[0] * 256 * 256 * 256
addressIntValue += address[1] * 256 * 256
addressIntValue += address[2] * 256
addressIntValue += address[3]

Затем вы можете отсортировать по адресу "addressIntValue".

1 голос
/ 11 мая 2010

Если вы не хотите анализировать IP вручную, вы можете использовать InetAddress class

InetAddress ia1 = InetAddress.getByName("192.168.0.9");
InetAddress ia2 = InetAddress.getByName("192.168.0.234");

System.out.println(ia1.hashCode() < ia2.hashCode());

Я использую метод hashCode(), потому что он возвращает адрес в виде числа для ipv4. Вы также можете сравнивать массивы, возвращаемые InetAddress.getAddress ()

РЕДАКТИРОВАНИЕ Использование hashCode() является недокументированной функцией, и могут возникнуть проблемы, если у вас есть адреса ipv6 и ipv4. Поэтому лучше сравнивать массивы байтов или преобразовывать их в число вручную.

...