Kolekcje mieszające w Javie, część 2

(ang. Hashing collections in Java, part 2)

Poprzednia część artykułu znajduje się tutaj: Kolekcje haszujące w Javie, część 1. Omówiliśmy sobie w niej ideę działania kolekcji haszujących w Javie. W tej części pokażemy jak kolekcje działają w praktyce i jak ważna jest poprawna implementacja metody hashCode.

Struktura danych

Zgodnie z poprzednią częścią w przykładzie wykorzystamy kolekcję przechowującą osoby o różnych imionach. Do reprezentowania osoby użyjemy poniższej klasy Person. Zwróć uwagę na implementację metody hashCode(). Czy jest to poprawna implementacja? Oczywiście, że nie. Pewnie już wiesz, że wszystkie obiekty trafią do tego samego kubełka. Czyli wg naszej wizualizacji (z poprzedniej części) wszystkie osoby trafią do tego samego pokoju.

W celu zobrazowania problemu, do metod equals() oraz hashCode() dodaliśmy wyświetlanie na konsoli informacji o wywołaniu tychże metod. Każdorazowe wywołanie jeden z metod zostanie wyświetlone na ekranie.

Klasa Person

import java.util.Objects;

public class Person {
    private String firstName;

    public Person(String firstName) {
        this.firstName = firstName;
    }

    @Override
    public boolean equals(Object obj) {
        // self check
        if (this == obj) {
            return true;
        }
        // null check
        if (obj == null) {
            return false;
        }
        // type check
        if (getClass() != obj.getClass()) {
            return false;
        }
        Person person = (Person) obj;
        // field comparison
        System.out.println("Run equals() for person with name " + firstName + " to compare with name " + person.firstName);
        return Objects.equals(firstName, person.firstName);
    }

    @Override
    public int hashCode() {
        System.out.println("Run hashCode() for Person with name: " + firstName);
        return 11;
    }
}

Klasa demonstracyjna HashingDemo

Pokażę teraz implementację klasy z metodą main. Posłuży ona do prezentacji działania kolekcji mieszającej, zaimplementowanej w klasie HashSet. Na początek utworzę zbiór zawierający jedenaście osób o różnych imionach. Następnie dodam do tego zbioru jeszcze jedną osobę o imieniu Kamil.

Przy okazji możesz zobaczyć, jak w ciekawy sposób można zainicjalizować kolekcję HashSet z wykorzystaniem strumienia.

package com.codeit4us.blog.hashing;

import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class HashingDemo {
    public static void main(String[] args) {
        String[] names = {"Adam", "Michal", "Anna", "Ewa", "Jakub", "Marcin", "Damian", "Julia", "Lila", "Sylwia", "Marek"};
        Set<Person> set = Stream.of(names).map(Person::new).collect(Collectors.toSet());
        System.out.println("Add Kamil to set");
        set.add(new Person("Kamil"));
    }
}

Jak myślisz jakie operacje są wykonywane na zbiorze przy dodawaniu kolejnych obiektów (osób)?

Na każdym obiekcie, zanim zostanie dodany do zbioru musi zostać wywołana metoda hashCode(). Po wykonaniu tej metody wiemy już do jakiego kubełka trafi nasz obiekt.

W przypadku pierwszego obiektu, czyli osoby o imieniu „Adam”, nasza kolekcja jest jeszcze pusta. Tak samo pusty jest też kubełek oznaczony wartością 11, która zwróciła metoda hashCode(). Wiadomo zatem, że nie ma innej osoby o tym imieniu. Także nie są wykonywane żadne operacje porównania metodą equals()

Kolejną osobą dodawaną do kolekcji jest „Michal”. Niestety nasza funkcja haszująca (bezwzględnie) prowadzi nas dokładnie do tego samego kubełka. Znajdue się w nim już jeden obiekt, osoba „Adam” dodana przed chwilą. W takim przypadku mamy do czynienia z tzw. kolizją. W związku z tym kolekcja musi sprawdzić czy obiekt znajdujący się obecnie w kubełku nie jest przypadkiem tym samym obiektem (w rozumieniu metody equals()).

Jak pamiętasz kolekcja typu Set nie pozwala przechowywać duplikatów. W przypadku próby dodanie obiektu, który jest już w kolekcji metoda add zwróci wartość false i obiekt nie zostanie dodany.

W związku z tym kolekcja porównuje dodawany obiekt z obiektem (lub obiektami) znajdującym się już w kubełku.

Podobnie przy dodawaniu kolejnych osób również obliczana jest wartość funkcji mieszającej, która oczywiście zwraca tę samą wartość. Znów trafiamy do tego samego kubełka. Znajdują się tam już dwa obiekty i każdy z nich musimy porównać z dodawanym. Czyli sprawdzamy, czy nie ma tam przypadkiem osoby o imieniu „Anna”.

Sytuacja będzie się powtarzać z tą różnicą, że za każdym kolejnym razem będziemy widzieć coraz więcej wywołań metody equals().

Po zainicjalizowaniu kolekcji dwunastoma obiektami dodajemy kolejną osobę o imieniu „Kamil”. Jak myślisz ile razy zostanie wywołana metoda hashCode() oraz metoda equals()?

hashCode() – 1 raz, equals() – 12 razy

Teraz możesz uruchomić klasę HashingDemo samodzielnie w edytorze online lub poniżej zobaczyć wynik działania programu:

Run hashCode() for Person with name: Adam
Run hashCode() for Person with name: Michal
Run equals() for person with name Michal to compare with name Adam
Run hashCode() for Person with name: Anna
Run equals() for person with name Anna to compare with name Adam
Run equals() for person with name Anna to compare with name Michal
Run hashCode() for Person with name: Ewa
Run equals() for person with name Ewa to compare with name Adam
Run equals() for person with name Ewa to compare with name Michal
Run equals() for person with name Ewa to compare with name Anna
Run hashCode() for Person with name: Jakub
Run equals() for person with name Jakub to compare with name Adam
Run equals() for person with name Jakub to compare with name Michal
Run equals() for person with name Jakub to compare with name Anna
Run equals() for person with name Jakub to compare with name Ewa
Run hashCode() for Person with name: Marcin
Run equals() for person with name Marcin to compare with name Adam
Run equals() for person with name Marcin to compare with name Michal
Run equals() for person with name Marcin to compare with name Anna
Run equals() for person with name Marcin to compare with name Ewa
Run equals() for person with name Marcin to compare with name Jakub
Run hashCode() for Person with name: Damian
Run equals() for person with name Damian to compare with name Adam
Run equals() for person with name Damian to compare with name Michal
Run equals() for person with name Damian to compare with name Anna
Run equals() for person with name Damian to compare with name Ewa
Run equals() for person with name Damian to compare with name Jakub
Run equals() for person with name Damian to compare with name Marcin
Run hashCode() for Person with name: Julia
Run equals() for person with name Julia to compare with name Adam
Run equals() for person with name Julia to compare with name Michal
Run equals() for person with name Julia to compare with name Anna
Run equals() for person with name Julia to compare with name Ewa
Run equals() for person with name Julia to compare with name Jakub
Run equals() for person with name Julia to compare with name Marcin
Run equals() for person with name Julia to compare with name Damian
Run hashCode() for Person with name: Lila
Run equals() for person with name Lila to compare with name Adam
Run equals() for person with name Lila to compare with name Michal
Run equals() for person with name Lila to compare with name Anna
Run equals() for person with name Lila to compare with name Ewa
Run equals() for person with name Lila to compare with name Jakub
Run equals() for person with name Lila to compare with name Marcin
Run equals() for person with name Lila to compare with name Damian
Run equals() for person with name Lila to compare with name Julia
Run hashCode() for Person with name: Sylwia
Run equals() for person with name Sylwia to compare with name Adam
Run equals() for person with name Sylwia to compare with name Michal
Run equals() for person with name Sylwia to compare with name Anna
Run equals() for person with name Sylwia to compare with name Ewa
Run equals() for person with name Sylwia to compare with name Jakub
Run equals() for person with name Sylwia to compare with name Marcin
Run equals() for person with name Sylwia to compare with name Damian
Run equals() for person with name Sylwia to compare with name Julia
Run equals() for person with name Sylwia to compare with name Lila
Run hashCode() for Person with name: Marek
Run equals() for person with name Marek to compare with name Adam
Run equals() for person with name Marek to compare with name Michal
Run equals() for person with name Marek to compare with name Anna
Run equals() for person with name Marek to compare with name Ewa
Run equals() for person with name Marek to compare with name Jakub
Run equals() for person with name Marek to compare with name Marcin
Run equals() for person with name Marek to compare with name Damian
Run equals() for person with name Marek to compare with name Julia
Run equals() for person with name Marek to compare with name Lila
Run equals() for person with name Marek to compare with name Sylwia
Add Marek to set
Run hashCode() for Person with name: Kamil
Run equals() for person with name Kamil to compare with name Anna
Run equals() for person with name Kamil to compare with name Anna
Run equals() for person with name Kamil to compare with name Ewa
Run equals() for person with name Kamil to compare with name Marcin
Run equals() for person with name Kamil to compare with name Marek
Run equals() for person with name Kamil to compare with name Michal
Run equals() for person with name Kamil to compare with name Jakub
Run equals() for person with name Kamil to compare with name Lila
Run equals() for person with name Kamil to compare with name Julia
Run equals() for person with name Kamil to compare with name Damian
Run equals() for person with name Kamil to compare with name Adam
Run equals() for person with name Kamil to compare with name Sylwia
Run equals() for person with name Kamil to compare with name Ewa
Run equals() for person with name Kamil to compare with name Jakub

Poprawiona metoda mieszająca

W idealnym przypadku w każdym kubełku powinien znajdować się co najwyżej jeden obiekt. W tym celu opieramy działanie metody hashCode() na polu firstName. Możemy użyć metody hashCode() z klasy String.

@Override
public int hashCode() {
    System.out.println("Run hashCode() for Person with name: " + firstName);
    return firstName == null ? -1 : firstName.hashCode();
}

Warto oczywiścię zabezpieczyć się na okoliczność stworzenia osoby bez imienia (firstName == null). Innym (nawet lepszym) rozwiązaniem jest sprawdzanie czy firstName jest null'em w konstruktorze klasy Person i rzucanie wyjątku w takim przypadku. Jednak nie to jest meritum sprawy w tym wpisie.

Teraz możesz ponownie uruchomić klasę HashingDemo samodzielnie w edytorze online lub poniżej zobaczyć wynik działania programu:

Run hashCode() for Person with name: Adam
Run hashCode() for Person with name: Michal
Run hashCode() for Person with name: Anna
Run hashCode() for Person with name: Ewa
Run hashCode() for Person with name: Jakub
Run hashCode() for Person with name: Marcin
Run hashCode() for Person with name: Damian
Run hashCode() for Person with name: Julia
Run hashCode() for Person with name: Lila
Run hashCode() for Person with name: Sylwia
Run hashCode() for Person with name: Marek
Add Marek to set
Run hashCode() for Person with name: Kamil

Podsumowanie części 2

Widzisz teraz jak ważne jest napisanie dobrej funkcji mieszającej. W najgorszym przypadku metoda equals musi zostać wywołana tyle razy ile jest elementów w kolekcji. W przypadku kolekcji zawierającej kilkaset tysięcy elementów może mieć to realny wpływ na szybkość działania programu.

W kolejnej poznasz bardziej zaawansowane tematy związane z wyliczaniem hasz kodu oraz kilka ciekawostek i porad związanych z kolekcjami mieszającymi.

Zapraszam do lektury kolejnej części, która powstanie wkrótce.

Kolekcje mieszające w Javie, część 2​
Tagi:            

Komentarzy do 0 thoughts on “Kolekcje mieszające w Javie, część 2​

  • 4 grudnia, 2020 z 10:04 pm
    Permalink

    Komentarz oczekuje na moderację

    1хбет – букмекерская контора, которая пользуется популярностью. Оформлена она на Кюрасао и функционирует еще с 1997 года, в интернет появилась с 2011 года. Число авторизованных пользователей постоянно растет. Значительный плюс заведения – отменные коэффициенты, которые сейчас обгоняют предложения остальных учреждений. Сегодня в распоряжении фирмы примерно 1000 пунктов по зачислению игровых ставок, главный интернет-сайт на 36 языках мира и использование новейших технологий для комфорта своих потребителей. 1xbet официальный сайт Портал букмекерской конторы с комфортным функционалом, который осилит даже новенький. Оформляется он в сине-белоснежном спектре. Непосредственно на главной странице найдете панель с таблицами, там просто сориентироваться. Если игрока интересует конкретный вид спортивных состязаний, следует обратить внимание на список в левой части ресурса, где в алфавитном распорядке указываются все виды спортивных состязаний. В центральной части можно рассмотреть идущие акции и специальные предложения. На сайте можно ознакомиться с прогнозом ставок на спорт, расценить мнение специалистов. Справой стороны привычное окно регистрации и прохода в учетную запись. Однако в какой степени безупречным не был портал, на этот адрес поставлена блокировка. С тем, чтобы ее обойти применяется зеркало.  1xbet зеркало на сегодня Зеркало – воспроизводит главный интернет-сайт с полным его перечнем возможностей. Просто-напросто изменяется имя домена, где портал не блокируется. Такой ресурс доступен постоянно и даже при проведении технологических действий и возможных атак. Актуален он для игроков из России, где ставки на спорт в режиме онлайн воспрещены, а подобные проекты просто-напросто блокируются. Только создатели уже задумали, как обойти блокировку. 1xbet зеркало рабочее на сегодня даёт возможность конторе предоставлять свои сервисы, пускай и не полностью законно. Просто-напросто чтобы иметь лицензию на прием ставок на спортивные мероприятия в РФ, необходимо внести не менее 30 млн руб. Даже если получить лицензию, то это повлечёт немалые расходы, какие повлияют на уменьшение коэффициентов. Многие клиенты станут интересоваться соперничающими фирмами и попросту перестанут ставить на этом проекте. Поэтому наиболее выгодное решение для конторы и самих участвующих – это применение зеркального сайта.  Для того, чтобы зайти в свой аккаунт необходимо ввести логин и пароль. Информация секретная и защищается от посторонних, по этой причине тревожиться за сохранность сведений нет смысла. Перед играющим раскрывается обычный функционал и функции аккаунта – статистика ставок, оборот по счету, денежные средства на счету, способность их вывода. В прочих же государствах применение услуг БК не запрещается, правда имеет возможность немножко видоизменяться само наименование ресурса. Поэтому нужно установить запрос: зеркало 1xbet рабочее на сегодня прямо сейчас и всякому абоненту будет представлен перечень актуальных гиперссылок. В основном БК самостоятельно рассылает гиперссылки оформленным пользователям просто на почтовый ящик, мобильное устройство, используя службы саппорта. Конечно, любой абонент сможет наведать официальный web-сайт БК, используя VPN. Сейчас представлено много приложений, которые позволяют менять IP-адрес. 1хбет букмекерской конторы Более тысячи мероприятий в сутки предоставляется сайтом. Любой игрок может осуществить подбор из классических спорт направлений – футбол, волейбол, и редких – крикет, флорбол. На первой же странице собраны самые центральные мероприятия в спортивном мире – Первенство мира по футболу или Стран Европы. Каждый может попробовать себя лично в ставках в online-варианте, и еще прогнозировать победителей престижных наград. Именно благодаря системе Multi-LIVE допустимо выполнение ставок непосредственно на множество игорных событий. В то же время отдельное спортивное мероприятие транслируется на веб-сайте. Раскрыв пункт «Финставки» и «Биржа криптовалют», возможно испробовать свою удачу и успешно заработать на денежных скачках. Новых игроков притягивает высокий коэффициент и низкая маржа. Лотереи, ТВ-шоу, ставки на погодные условия, сериалы – разнообразие мероприятий порадует каждого зарегистрированного играющего букмекерской конторы. Следует наведать 1xbet официальный сайт, который приятно изумит своим перечнем возможностей. Пользоваться услугами конторы смогут только лишь оформленные игроки. Сервис 1xZone обеспечивает не только лишь графическую передачу, но и игровые ставки на события, происходящие в момент последующего поединка.   Операция регистрации займет короткий отрезок времени. А для комфорта клиентов на 1xbet регистрация происходит одним из вариантов: Укажите свой телефонный номер и устройте привязку к нему. Пользуйтесь иконкой одной из социальных сетей, где вы уже зарегистрированы. Напишите e-mail. Очень популярный и немудреный метод заключительный, для него требуется подтверждение учетной записи используя почту и переход по гиперссылке. Выбирайте сложный пароль с цифрами и знаками, для того, чтобы его было трудно вскрыть. Воспользоваться услугами фирмы смогут лица, которым 18 лет. Чтобы получить выигранные денежные средства со счета, необходимо заполнить профиль и внести индивидуальные сведения. Однако беспокоиться не стоит, контора гарантирует их сохранность. Промокоды 1xbet Игроков букмекерской конторы привлекает большое количество акций и скидок для постоянных игроков и новеньких. Хорошие презенты готовы имениннику –  промокод 1xbet или подъём коэффициента на отдельные игры. Регистрация с промокодом даёт возможность преумножить сумму денег, положенную на счет. Для этого начинающий пользователь проходит аутентификацию, вносит на свой счет 100 рублей и принимает до 6500 рублей. Только снять их невозможно, до тех пор, пока не отыграешь. Приветственный бонус вручается при первом внесении депозита. Вложенная сумма обязана быть примерно 100 евро в этом случае получите такой же эквивалент. Только отыгранные денежные средства ставят на вывод. А тем, кто систематически терпит неудачи, можно выиграть карточки. Все это создано для того, чтобы игроки сохраняли интерес к процессу игры и оттачивали свое искусство.   Для дополнения счета игрока применяются распространенные системы оплаты. Электронные кошельки Qiwi, WebMoney, а также обычные карточки VISA, MasterCard. Допустимо дополнение через банковский перевод, сообщение и салоны связи. Денежная единица игрового счета бывает разной – в долларах, рублях, евро. Вместе с тем вывод делается на привязанный к аккаунту кошелек, что в свою очередь обеспечивает защищенность и надежность денежных средств. Наименьшая сумма получения равняется 2 евро или 3 доллара. Только лишь после подтверждения личности возможно зайти в кабинет и оформить заказ на вывод. В случае, если нет никаких проблем, то она выполняется моментально, вначале может пройти до 3 дней. Скачать 1xbet на андроид Следует скачать 1xbet на андроид и айфон, так как программа раскрывает перед пользователями множество возможностей. С ним вы неизменно будете знать о новых мероприятиях и сможете держать под контролем собственные ставки на спорт. Скачивается платформа для Android и IOS, что позволяет установить его на любые прогрессивные девайсы – телефоны, планшеты. Программа открывает вход к аккаунту и прочим функциям вебсайта. Только одно, что остается недоступным – функциональность «1хZone» и непосредственная трансляция. Авторы теперь уже работают над устранением этих моментов. Для тех, кто регулярно вояжирует не хочет открываться от мира игровых ставок, такое приложение будет подлинным спасением. Сайт приспосабливается под дисплей применяемого устройства. Ставки делаются попросту в приложении. Если у вас появились затруднения при выводе денежных средств либо ваша ставка долго не рассчитывается, не волнуйтесь, лучше всего сразу обратиться за помощью в службу саппорта. Работники службы поддержки доступны игрокам в течении 24 часов в сутки и готовы ответить на все интересующие вопросы. Наибольшее время обработки обращения – сутки, однако откликнуться стремятся раньше. Любой игрок сможет самостоятельно выбрать подходящий метод связи: – через online; – по указанным на сайте контактным сведениям. Другой связью является написание электронного письма либо заполнение online-формы «Консультант-онлайн». Работая в режиме чата каждый игрок имеет ответ на вопрос. Все спорные моменты находят решение, консультанты стараются определиться в каждой обстановке, найти индивидуальный подход. Подобная публичность букмекерской конторы располагает к себе и число игроков только увеличивается.

    Powtórz

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *