#java #arraylist
#java #arraylist
Вопрос:
У меня есть 2 ArrayLists, которые содержат массив строк в качестве «компонента». Я хочу найти «компоненты», первый элемент которых одинаков в обоих ArrayLists. Чтобы было более понятно:
ArrayList One
first component => {"0", "zero"}
second component => {"1", "one"}
ArrayList Two
first component => {"1", "uno"}
second component => {"2", "two"}
Я хотел бы выполнить цикл по ArrayList Two и найти {«1», «uno»}.
Пока что у меня есть вложенный цикл, который перебирает первый массив, а затем проверяет текущий компонент для каждого компонента в ArrayList Two.
for(int i=0; i<One.size(); i )
{
for(int j=0; j<Two.size(); j )
{
if( fileOne.get(i)[0].equals( Two.get(j)[0] ) )
{
System.out.print( Two.get(j)[0] " " );
System.out.print( Two.get(j)[1] );
System.out.println();
}
}
}
Я думаю, что должно быть лучшее решение. Любая помощь
Ответ №1:
Используйте HashSet.
Set<String> set = new HashSet<String>()
for(int i=0; i<One.size(); i ) {
set.add(fileOne.get(i)[0]);
}
for(int i=0; i<Two.size(); i ) {
String component[] = Two.get(j)
if(set.contains(component[0])) {
System.out.print( component[0] " " );
System.out.print( component[1] );
System.out.println();
}
}
Примечание: Список не будет работать в этом случае, потому что поиск в списках равен O (N). Поиск в HashSets равен O (1), поэтому построение набора (первый цикл) равно O (N). Тогда просмотр вашего второго массива равен O (M), а каждый поиск равен O (1).
В целом, это становится O (N) ( O (M) * O (1) ) = O (N M)
Редактировать: для комментариев Ted.
Комментарии:
1. Вероятно, это решение с большей экономией памяти, чем мое. Однако, чтобы получить желаемый результат операции, измените тело
if
наSystem.out.println( Two.get(j)[0] " " Two.get(j)[1] );
. (Здесь помогла бы временная переменная. 🙂 )
Ответ №2:
Вы могли бы попробовать использовать hashmap. Инициализируйте его из первого ArrayList путем сопоставления первого элемента каждого компонента с компонентом (или индексом компонента). Затем для каждого компонента второго ArrayList вы можете выполнить поиск по первому элементу каждого компонента, чтобы найти соответствующий компонент (или обнаружить, что его нет, когда он возвращается null
).
Комментарии:
1. Хэширование всего списка = O (1) * n. Поиск всех элементов = O (1) * m. Итак, я думаю, если я что-то не пропустил, решение Ted — O (n m), это правильно? Опять же, хеширование похоже на сортировку, поскольку оно позволяет ускорить поиск..
2. @Kyle — Я считаю, что это O (n m), точно так же, как решение преподобного Гонзо.
3. Да, это по сути то же самое, что и у меня.
Ответ №3:
Используйте два набора хэшей и метод retainAll таким образом, чтобы:
One.retainAll(Two)
С точки зрения сложности лучше — только O (n m) против вашего O (n * m). И с точки зрения удобства чтения и сопровождения также лучше. Обратите внимание, что retainAll
это изменит hashset One
, если вы не хотите, чтобы поведение создавало третью копию.
Комментарии:
1. Однако элементы не обязательно должны быть одинаковыми. Каждый элемент представляет собой массив строк, и я хочу, чтобы совпадал только первый элемент в массиве строк.
2. Это не проблема. Определите класс, содержащий массив, и реализуйте методы
hashCode
иequals
таким образом, чтобы проверялся только первый элемент массива. Затем создайте экземпляры этого класса и используйте их внутри хэш-наборов.
Ответ №4:
(отредактировано в ответ на комментарий Ted)
Без работы по инициализации, такой как сортировка / хеширование или поддержание отсортированного / хэшированного списка, лучшего решения не существует, оптимальным решением является O (n * m), которое у вас есть. Это оптимальное решение, потому что вам нужно сравнивать каждый элемент с любым другим элементом.
Я должен также упомянуть, что в определенных сценариях может быть разумнее сохранить список отсортированным. Тогда вместо сравнения каждого элемента вы могли бы использовать двоичный поиск или что-то в этом роде. Но без предварительной сортировки вашего списка, да, вам придется сравнить все элементы. Я считаю, что наилучшее возможное время сортировки — O (nlgn). Затем после этого процесса сортировки вам все равно придется искать свой элемент в отсортированном списке, но поиск по отсортированному списку может быть быстрее, чем поиск по несортированному.
Комментарии:
1. Нет необходимости сравнивать каждый элемент с любым другим. Индексирование структур данных может творить чудеса, чтобы разложить эту проблему на одну, которая равна O (n m). Даже простая сортировка обоих массивов и последующее использование этого в своих интересах даст лучшую производительность, чем O (n * m).
2. Безусловно, есть лучшее решение. Используйте хэши.
3. @ted, @преподобный .. смотрите мой комментарий к сообщению Ted. Я указывал, что без выполнения дополнительной работы по «инициализации» он не мог бы сделать лучше. Я должен был также упомянуть хеширование, но не подумал об этом.. Я думаю, тот факт, что я упомянул, что сортировка приведет к повышению производительности, в основном то же самое.
4. Эта цитата: «Оптимальным решением является O (n * m)», совершенно неверна. Сортировка — это не то же самое, что ее хэширование.
5. @преподобный Я знаю разницу между сортировкой и хешированием. Я говорил, что они похожи только в том отношении, что они позволяют выполнять более быстрый поиск, что является правдой. (Но да, эта цитата была совершенно неправильной, я согласен.. Я отредактировал сообщение, чтобы OP не видел неточную информацию)