Учитывая список IP-адресов, как вы находите min, max?

в Java у меня есть arrayList ip-адреса. как мне найти min и Max ?

я использовал коллекцию.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 ответов


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

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

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


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

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

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

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

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-интерфейс ссылки


ссыль Java-IP-адрес для Integer и обратно

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, а затем применил коллекцию.минута() Затем я преобразую long в int, а затем обратно в String. Для получения отсортированной строки ip-адресов.

спасибо


Если вы рассматриваете IP-адреса как целое число (long), вы можете сортировать по нему. Напишите пользовательский компаратор, который может разделить IP-адрес на массив ints, а затем создать общее значение 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".


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

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. Поэтому лучше всего сравнивать массивы байтов или конвертировать их в число вручную.