Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.72/18: Рейтинг темы: голосов - 18, средняя оценка - 4.72
 Аватар для FatNinja
82 / 82 / 32
Регистрация: 17.02.2016
Сообщений: 226

Best practice Comparator и null-значения

18.02.2016, 22:44. Показов 3570. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер.
В одном из учебных задач потребовалось использовать Comparator для сортировки массива.
Java
1
2
3
4
5
6
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getFaculty().compareToIgnoreCase(o2.getFaculty());
            }
        });
Собственно всё работает, ровно до момента появления null в массиве students или поле faculty - валится с NPE.
Пару минут погуглив нашёл такое решение - теперь null не страшен в обоих случаях:
Java
1
2
3
4
5
6
7
8
9
10
11
12
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return (o1 == null) ?
                    ((o2 == null) ? (0) : (Integer.MIN_VALUE)) :
                    ((o2 == null) ? (Integer.MAX_VALUE) : 
                        (o1.getFaculty() == null) ?
                        ((o2.getFaculty() == null) ? (0) : (Integer.MIN_VALUE)) :
                        ((o2.getFaculty() == null) ? (Integer.MAX_VALUE) :  
                            (o1.getFaculty().compareToIgnoreCase(o2.getFaculty()))));
            }
        });
Я так понимаю это решение для параноиков или для сильно отказоустойчивых систем.
Хотелось бы узнать у опытных джавистов - какой вариант используется на реальных проектах чаще?
Стоит ли заморачиваться с проверками на null и в какой степени.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
18.02.2016, 22:44
Ответы с готовыми решениями:

EF: null-значения
Есть такое описание свойства: public class SomeUnit { public int? SomeValue { get; set; } } Есть...

null значения
что делать в таком случае: в linq запросе я сравниваю столбец со значением, причем столбец содержит null значения, и выдает ошибку из-за...

Возвращение значения null
как поступить в данном случае, при запросе WMI к классу WIN32_Processor посредством L2CacheSize конструктор выдает ошибку о том что...

9
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
18.02.2016, 23:25
Лучший ответ Сообщение было отмечено FatNinja как решение

Решение

Цитата Сообщение от FatNinja Посмотреть сообщение
Хотелось бы узнать у опытных джавистов - какой вариант используется на реальных проектах чаще?
В реальных проектах списки не содержат null, равно как и свойства объектов.

Цитата Сообщение от FatNinja Посмотреть сообщение
Стоит ли заморачиваться с проверками на null и в какой степени.
Не стоит использовать null.

Добавлено через 27 минут
FatNinja, но, допустим, раз уж так получилось, то:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public final class Student {
    
    public static final Comparator<Student> BY_FACULTY_IGNORE_CASE
            = (left, right) -> left.getFaculty().compareToIgnoreCase(right.getFaculty());
 
    public static Student create(final String name, final String faculty) {
        Objects.requireNonNull(name, "name must not be null");
        Objects.requireNonNull(faculty, "faculty must not be null");
        return new Student(name, faculty);
    }
    
    private final String name;
    private final String faculty;
    private final String string;
    
    private Student(final String name, final String faculty) {
        this.name = name;
        this.faculty = faculty;
        this.string = "Student{" + "name=" + name + ", faculty=" + faculty + '}';
    }
    
    public String getFaculty() {
        return faculty;
    }
 
    @Override
    public String toString() {
        return string;
    }
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public final class StudentsSortTest implements Test {
    
    private final Student[] students = {
        Student.create("Vasya", "Computer Science"),
        Student.create("Petya", "Computer Science"),
        Student.create("Kolya", "Software engineering"),
        Student.create("Dasha", "Software engineering"),
        Student.create("Sveta", "Marketing"),
        Student.create("Katya", "Economics")
    };
 
    @Override
    public void run() {
        final Student[] sorted = Arrays.stream(students)
                .filter(s -> s != null)
                .filter(s -> s.getFaculty() != null)
                .sorted(Student.BY_FACULTY_IGNORE_CASE)
                .toArray(size -> new Student[size]);
        Arrays.stream(sorted).forEach(System.out::println);
    }
}
2
 Аватар для FatNinja
82 / 82 / 32
Регистрация: 17.02.2016
Сообщений: 226
18.02.2016, 23:31  [ТС]
korvin_, спасибо. Красивое решение
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
19.02.2016, 14:25
Лучший ответ Сообщение было отмечено FatNinja как решение

Решение

Если очень нужно, можно и null-ы оставить. В java 8 появились удобные статические методы для создания компараторов. Comparator.nullsFirst/nullsLast например
Java
1
2
public static final Comparator<Student> BY_FACULTY_IGNORE_CASE =
    Comparator.nullsFirst((left, right) -> left.getFaculty().compareToIgnoreCase(right.getFaculty()));
2
0 / 0 / 0
Регистрация: 30.01.2017
Сообщений: 1
24.07.2017, 12:21
korvin, Ваш код выглядит замечательно, но мне не понятна реализация интерфейса Test:
Цитата Сообщение от korvin_ Посмотреть сообщение
public final class StudentsSortTest implements Test
Где он? Как он выглядит?
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
24.07.2017, 13:26
Цитата Сообщение от turbanoff Посмотреть сообщение
Java
1
Comparator.nullsFirst((left, right) -> left.getFaculty().compareToIgnoreCase(right.getFaculty()));
можно еще короче и понятнее
Java
1
Comparator.nullsFirst(Comparator.comparing(Student::getFaculty))
Добавлено через 1 минуту
правда он будет без ignoreCase
0
502 / 348 / 134
Регистрация: 14.06.2016
Сообщений: 669
24.07.2017, 14:47
Java
1
Comparator.nullsFirst(Comparator.comparing(Student::getFaculty, String.CASE_INSENSITIVE_ORDER))
0
 Аватар для FatNinja
82 / 82 / 32
Регистрация: 17.02.2016
Сообщений: 226
24.07.2017, 16:14  [ТС]
Некропостеры, блин
До кучи ещё и ответы неверные.

Код для демонстрации:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.util.Arrays;
import java.util.Comparator;
 
public class Runner {
    public static void main(String[] arguments) {
 
        Student[] students = new Student[] {
            new Student(1L, "Sam", "antique culture"),
            new Student(2L, "John", "Physical"),
            new Student(3L, "Alice", "Psihology"),
            new Student(4L, "Fil", null),
            null,
            new Student(6L, "Joshua", "Antique culture"),
            new Student(7L, "Mark", "Mathematical"),
            null
        };
 
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
// solving 1
 
//        Arrays.sort(students, new Comparator<Student>() {
//            @Override
//            public int compare(Student o1, Student o2) {
//                return (o1 == null) ?
//                    ((o2 == null) ? (0) : (Integer.MIN_VALUE)) :
//                    ((o2 == null) ? (Integer.MAX_VALUE) : 
//                        (o1.getFaculty() == null) ?
//                        ((o2.getFaculty() == null) ? (0) : (Integer.MIN_VALUE)) :
//                        ((o2.getFaculty() == null) ? (Integer.MAX_VALUE) :  
//                            (o1.getFaculty().compareToIgnoreCase(o2.getFaculty()))));
//            }
//        });
 
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
// solving 2
 
//      final Comparator<Student> BY_FACULTY_IGNORE_CASE = 
//              (left, right) -> left.getFaculty().compareToIgnoreCase(right.getFaculty());
//      students = Arrays.stream(students)
//                .filter(s -> s != null)
//                .filter(s -> s.getFaculty() != null)
//                .sorted(BY_FACULTY_IGNORE_CASE)
//                .toArray(size -> new Student[size]);
 
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
// solving 3
 
//        Arrays.sort(students, Comparator.nullsFirst(
//          Comparator.comparing(Student::getFaculty, String.CASE_INSENSITIVE_ORDER)));
 
        Arrays.stream(students).forEach(System.out::println);
    }
}
 
class Student {
    private long id;
    private String name;
    private String faculty;
    
    public Student() {}
    
    public Student(long id, String name, String faculty) {
        this.id = id;
        this.name = name;
        this.faculty = faculty;
    }
 
    public String getFaculty() {
        return faculty;
    }
 
    public void setFaculty(String faculty) {
        this.faculty = faculty;
    }
 
    @Override
    public String toString() {
        return "\t" + id + "\t" + name + "\t\t" + faculty;
    }
}


Вывод без "сортировки":
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
    1   Sam     antique culture
    2   John        Physical
    3   Alice       Psihology
    4   Fil     null
null
    6   Joshua      Antique culture
    7   Mark        Mathematical
null


Вывод монструозным компаратором, который я использовал в первом сообщении:
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
null
null
    4   Fil     null
    1   Sam     antique culture
    6   Joshua      Antique culture
    7   Mark        Mathematical
    2   John        Physical
    3   Alice       Psihology


Вывод способом, предложенным korvin_ и дополненным turbanoff - почти то что нужно, за исключением того, что из результата удаляется null значения и значения с "факультетом" null. Условно это можно принять за хороший ответ:
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
    1   Sam     antique culture
    6   Joshua      Antique culture
    7   Mark        Mathematical
    2   John        Physical
    3   Alice       Psihology


Решения LeX и vcrop всё так же падают с NPE, так как не могут переварить значение null в поле faculty. Внимательнее читайте первое сообщение
0
502 / 348 / 134
Регистрация: 14.06.2016
Сообщений: 669
24.07.2017, 16:36
Дописал только ignoreCase на предыдущее.
Давай еще solving 4
Java
1
2
    public static final Comparator<Student> BY_FACULTY_IGNORE_CASE
            = Comparator.nullsFirst(Comparator.comparing(Student::getFaculty, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)));
1
 Аватар для FatNinja
82 / 82 / 32
Регистрация: 17.02.2016
Сообщений: 226
24.07.2017, 17:01  [ТС]
vcrop, теперь ОК

Цитата Сообщение от vcrop Посмотреть сообщение
Давай еще solving 4
Не надо воспринимать в штыки. Темы форума индексируются в поиске и решения с ошибкой не слишком помогут страждущим в их проблемах в будущем.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
24.07.2017, 17:01
Помогаю со студенческими работами здесь

Проверка значения на null в БД
Добрый день. С помощью ODBC обращаюсь к СУБД MySQL. OdbcCom = new System.Data.Odbc.OdbcCommand(&quot;SELECT * FROM users...

Обработка NULL значения
Доброго времени суток. Есть SQL запрос набранный в Access 2007 SELECT RESULT_ChipIN, RESULT_IN, RESULT_ChipOUT, RESULT_OUT FROM ...

Вывести Null значения из БД в DropDownListFor
Здравствуйте такой вопрос, мне нужно вывести в DropdownListFor, которые хранятся в базе, но некоторые из них могу быть null, как мне...

SQLite таблицы и NULL значения
Все доброго времени суток! Имеется SQLite БД в ней создаю таблицу. Подскажите пожалуйста, является ли подход правильный как...

Передача значения Null в конструктор
Этот вопрос попался на тестировании using System; using System.Collections.Generic; using System.Linq; using System.Text; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! в-строка - входное арифметическое выражение в инфиксной(обычной). . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru