From 4c1075b12462bf2bb86c756142e8590e857e2ba7 Mon Sep 17 00:00:00 2001 From: Marchenko Dmitriy Date: Thu, 9 Oct 2025 13:47:32 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=202=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/naumen/collection/task2/Task2.java | 93 ++++++++++++++++++- .../java/ru/naumen/collection/task2/User.java | 34 ++++++- 2 files changed, 122 insertions(+), 5 deletions(-) diff --git a/src/main/java/ru/naumen/collection/task2/Task2.java b/src/main/java/ru/naumen/collection/task2/Task2.java index 83278f8..1d1f4a5 100644 --- a/src/main/java/ru/naumen/collection/task2/Task2.java +++ b/src/main/java/ru/naumen/collection/task2/Task2.java @@ -1,7 +1,9 @@ package ru.naumen.collection.task2; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Дано: @@ -34,9 +36,94 @@ public class Task2 /** * Возвращает дубликаты пользователей, которые есть в обеих коллекциях + *

+ * Принцип работы: + *

+ * Такой подход позволяет оптимизировать работу метода при значительной разнице в размерах + * коллекций, сохраняя при этом хорошую производительность при близких размерах. + *
+ * Временная сложность в худшем случае: O(n + m), где n и m - размеры коллекций. + * Пространственная сложность: O(min(n, m)) для хранения меньшей коллекции в HashSet. + *
+ * Таким образом, метод эффективно находит дубликаты пользователей в обеих коллекциях + * с оптимальной производительностью. + *

+ *

+ * Причина выбора коллекции HashSet: + * HashSet обеспечивает среднее время доступа O(1) для операций + * добавления и проверки наличия элемента (в случае правильно + * написанных {@link User#equals(Object)} и {@link User#hashCode()}), что делает его идеальным + * выбором для хранения пользователей при поиске дубликатов. + * Такой выбор коллекций обеспечивает оптимальную производительность и удобство + * при реализации метода поиска дубликатов. + *

+ * Примечание: Метод {@link #findCommonUsers} используется для фильтрации одной коллекции + * на основе наличия элементов в множестве, что обеспечивает эффективный поиск общих + * пользователей. + * @param collA коллекция A + * @param collB коллекция B + * @return список дубликатов */ public static List findDuplicates(Collection collA, Collection collB) { - // TODO реализовать метод - return null; + final double SIGNIFICANT_RATIO = 2.0; + + double sizeA = collA.size(); + double sizeB = collB.size(); + + if (sizeA == 0 || sizeB == 0) { + return List.of(); + } + + double ratio = Math.max(sizeA, sizeB) / Math.min(sizeA, sizeB); + + if (ratio > SIGNIFICANT_RATIO) { + Collection smallerCol = sizeA > sizeB ? collB : collA; + Collection largerCol = sizeA > sizeB ? collA : collB; + + Set smallerSet = new HashSet<>(smallerCol); + + return findCommonUsers(largerCol, smallerSet); + } else { + + Set setA = new HashSet<>(collA); + + return findCommonUsers(collB, setA); + } + } + /** + * Находит общих пользователей между коллекцией и множеством + *
+ *

Принцип работы: + * Берём коллекцию пользователей для проверки и фильтруем её, + * оставляя только тех пользователей, которые содержатся в множестве. + * Использование множества (Set) позволяет эффективно проверять наличие + * пользователя благодаря быстрому доступу по хешу.

+ *

+ * Временная сложность: O(n), где n - размер коллекции usersToCheck, + * так как для каждого пользователя выполняется операция проверки + * наличия в множестве, которая в среднем выполняется за O(1). + *

+ *

+ * Пространственная сложность: O(1), если не учитывать входные данные, + * так как дополнительная память используется только для хранения + * результата. + *

+ * Таким образом, метод эффективно находит общих пользователей + * между коллекцией и множеством с оптимальной производительностью. + * + * @param usersToCheck коллекция пользователей для проверки + * @param userSet множество пользователей для сравнения + * @return список общих пользователей + */ + private static List findCommonUsers (Collection usersToCheck, Set userSet) { + return usersToCheck.stream() + .filter(userSet::contains) + .toList(); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/naumen/collection/task2/User.java b/src/main/java/ru/naumen/collection/task2/User.java index 0803b0b..3c6560d 100644 --- a/src/main/java/ru/naumen/collection/task2/User.java +++ b/src/main/java/ru/naumen/collection/task2/User.java @@ -1,8 +1,16 @@ package ru.naumen.collection.task2; +import java.util.Arrays; +import java.util.Objects; + /** * Пользователь - * + *
+ * Класс с переопределёнными методами equals и hashCode для корректного сравнения объектов User. + * Метод equals сравнивает все три поля: username, email и passwordHash + * (используется Arrays.deepEquals для сравнения массивов). + * Метод hashCode генерирует хеш-код на основе всех трёх полей, используя Arrays.hashCode + * для массива passwordHash. * @author vpyzhyanov * @since 19.10.2023 */ @@ -10,4 +18,26 @@ public class User { private String username; private String email; private byte[] passwordHash; -} + + /** + * Сравнение объектов User + * @param o объект для сравнения + * @return true, если объекты равны, иначе false + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(username, user.username) && Objects.equals(email, user.email) && Objects.deepEquals(passwordHash, user.passwordHash); + } + + /** + * Получение хеш-кода объекта User + * @return + */ + @Override + public int hashCode() { + return Objects.hash(username, email, Arrays.hashCode(passwordHash)); + } +} \ No newline at end of file