Вход | Регистрация
    1  2  3   

Java. Удалить в ArrayList массив строк.

Java. Удалить в ArrayList массив строк.
Я
   yavasya
 
23.03.20 - 12:18
Допустим мне в ArrayList нужно удалить 1,3,5 строку. В 1С для этого создается массив строк для удаления, и далее в метод удалить куда передается массив строк. Как сделать такую операцию в джава  чтобы индексы не сбивались ? Или остается строка с ссылкой null ?
 
 
   Конструктор1С
 
101 - 24.03.20 - 03:49
(96) это может быть академическая задача из курса по программированию или учебника какого. Академические задачки по программированию часто отличаются бессмысленностью и беспощадностью
   Salimbek
 
102 - 24.03.20 - 09:09
У автора задача - Имеется ArrayList и в массиве индексы строк (х.з. как полученных), которые надо удалить из этого ArrayList.

Самый оптимальный вариант, по моему, в (56), т.к. выполняется не просто за O(n), а еще и это самое O - можно реализовать довольно эффективно.
А что касаемо (87), то у вас спрятаны дополнительные O(k*log(k)) во фразе "Положи в HashSet" и множитель O(log(k)) в "проверяй if(set.contains(value))" Итого сложность будет: O(k*log(k))+O(n*log(k))
   Сияющий в темноте
 
103 - 24.03.20 - 10:06
(99) копирование массива-быстрая операция?
а если в массиве миллион элементов
вот после таких рассуждений пишется код,который на реальных данных уходит в down,и никто не понимает,что случилось.
   yavasya
 
104 - 24.03.20 - 10:12
(103) да, потому что нативный метод, а jvm не умеет работать с памятью так же хорошо как c++ .
   MadHead
 
105 - 24.03.20 - 10:39
(97) В JS массивы - это скоере ассоциативный(индекс->значение) массив чем классический, сравнение не очень корреткное. То есть в джаве нужно вручную создать пары индекс-значение после чего уже можно преобразовать коллекцию в stream и применить фильтр. Есть либы которые реализовую метод zipWithIndex.  
(99) При увеличении точно происходит копирование в новую область большего рамера и при уменьшении скорее всего тоже.
(103) Копирование массива операция относительно быстрая, соизмеримая с подобной операцией в C/C++ но сложность операции O(N). В принципе сложность описывает как зависит время выполнения от ко-ва элементов и не говорит ничего о реальном времени выполнения. Если размер коллекции сильно меняется, то есть более оптимальные структуры для хранения таких данных. В Скале на пример есть Vector который по сути явялется деревом с массивами в узлах размерностью 32элемента. Это позволяет совместить плюсы linkedlist и arraylist. Большой плюс, что такая коллекция оптимально использует кэш процессора при итерации, так как 32-х разрядные массивы помещаются в кэш линию
   fisher
 
106 - 24.03.20 - 10:53
(103) Копирование с помощью System.arrayCopy - относительно быстрое даже на больших объемах. Насколько я понимаю, под капотом оно использует команды процессора блочного копирования памяти или что-то в этом духе. Встречал на просторах сравнение с обычным поэлементным копированием и копированием через этот метод - разница больше чем на порядок. Типа миллион элементов где-то 200 мс поэлементно у кого-то заняло, а этой хренью то ли за 10, то ли за 15 мс скопировало. Понятно, что голову все равно включать надо. Но все равно ArrayList остается самой универсальной реализацией динамического массива.
   fisher
 
107 - 24.03.20 - 10:57
А удалять или занулять элементы - это тоже всегда компромисс и решается по месту. Если массив не слишком большой - лучше удалять. Тем более, что removeIf делает это оптимизированно. Обслуживать разряженный массив - тоже не фунт изюму и легко может в итоге привести к неожиданным сайд-эффектам.
   sevod
 
108 - 24.03.20 - 11:04
Хочешь на Java-велосипед, колеса невообразимой формы? Зайди на 1С форум!
Вася, не удаляй из ArreyList ничего, ты еще не дорос до такого сверх высокого уровня. Ведь для этого нужно прочитать что такое ArreyList, а так же ознакомиться с другими коллекциями Java. Это ведь целый 8-ой уровень JavaRush (когда то до 10 было бесплатно, сейчас не знаю).
Вася, забудь слово ООП. Учи с начала. Возьми какой нибудь готовый курс и с нуля. Последовательно. Без пропусков.
Смещение индексов в ArreyList при добавлении/удалении элементов, это то, ради чего его и создавали. А ты с этим зачем то борешься. Для того что бы это понять, нужно сравнивать с Arrey. Но ведь для того, что бы это понять, придется почитать об этом. Методом тыка может не прокатить.
   yavasya
 
109 - 24.03.20 - 11:07
(108) качественный троль
   sevod
 
110 - 24.03.20 - 11:09
(109) это был лучший ответ в этой ветке. У меня чуть пукан не разорвало когда я это все читал. И я реально на 8 лвл javarush и там реально проходят коллекции.
Тебе реально рано с массивами работать, учи с нуля!
   yavasya
 
111 - 24.03.20 - 11:10
(108) я кстати на курсе программирования, то что сделать можно и как сделать я знаю. основных вопрос 1. Как сделать правильно и оптимально
   yavasya
 
112 - 24.03.20 - 11:11
(110) ну и на каком уровне там разбираются? удалил элемент и молодец? умничай для себя . не буду кормить тролей
   sevod
 
113 - 24.03.20 - 11:12
(111) а чего ты тогда основ не знаешь? и главное, почему ты этот вопрос на своем курсе не задал?!
   fisher
 
114 - 24.03.20 - 11:13
(105) Пошел почитать за класс Vector. Жутко было интересно, как же они перебалансируют дерево при удалениях/добавлениях. А оно иммьютбл. Ыыыыыы :)
   antgrom
 
115 - 24.03.20 - 11:15
(110) 8 уровень javarush это невысокий уровень. Любой 1Сник пройдёт легко, без предварительных знаний java. Нужно только время - несколько дней.
   sevod
 
116 - 24.03.20 - 11:19
(115) а я о чем? это околонулевой. Поэтому и пишу на полном серьезе что бы начал с нуля. Если прочитает что такое ArrayList и просто Array, то поймет какой он вопрос задал.
   fisher
 
117 - 24.03.20 - 11:20
(105) Я теперь вообще не понимаю, нахрена там внутри дерево, если оно иммьютбл. Что это дает в сравнении с обычным иммьютбл-массивом? Где про это почитать можно?
   sevod
 
118 - 24.03.20 - 11:24
(117) скорее всего для совместимости оставили. Что бы древний код не помер. Загугли по этому дереву, если попадешь на оф. документацию, возможно где то на странице будет рекомендованные на данный момент методы.
Там много таких. К примеру Date тоже лучше не использовать.
   fisher
 
119 - 24.03.20 - 11:26
(118) Речь про Scala
   fisher
 
120 - 24.03.20 - 11:30
(105) Могу только предположить, что это позволяет делать хитрые оптимизации при операциях над векторами. Чтобы не копировать неизменные блоки, уменьшая общее количество копирований.
   MadHead
 
121 - 24.03.20 - 11:35
(117) Имьютабл в прицепе функциональный подход - это по максимум отказаться от мутабельных объектов. Но оверхед не такой большой, так как при копировании сами массивы не пересоздаются. И отсуствие сайд эффектов позволяет обрабатыват коллекции многопоточно без синхронизации.
К примеру есть коллекция содержащий 320 элементов - это 10 массивов по 32 элемента для vector или массив 320элементов.
1a. При добавлении элемента в vector скопируется 10 ссылок + выделиться дополнительный массив размером 32
1b. При добавлении элемента в массив будет выделена область памяти под все данныее нового размера, а старые будут удалены.
   MadHead
 
122 - 24.03.20 - 11:39
(120) Массив даст все те же приемущества в плане векторных вычислений. Что бы быть на одной странице поясню, что я имею в виду под векторными вычислениями.
Современные процессоры подддерживают векторыне операции - то есть позволяют сделать 8 и более арифметических однотипных операция за одину операцию. Это дает существенный прирост в производительности CPU операций (активно используется в pandas и Apache arrow)
   fisher
 
123 - 24.03.20 - 11:50
(121) Идея понятна. Прикольно. В среднем ArrayList будет быстрее. Зато тут иммьютбл со всеми своими плюшками и одинаковое время выполнения операций без внезапных просадок.
   Конструктор1С
 
124 - 24.03.20 - 12:03
(104) "jvm не умеет работать с памятью так же хорошо как c++"

Ты сильно заблуждаешься. Так было лет 20 назад. Современная джавамашина сама умеет хитро оптимизировать код, к тому же позволяет произвести тонкую настройку. На плюсах можно написать более производительный код, но для этого требуется:
а) высокая квалификация плюсника
б) дофига времени
в 99% случаев овчинка выделки не стоит
   MadHead
 
125 - 24.03.20 - 12:21
(123) Если брать среднюю температуру по больнице, то можно сказать что в среднем arraylist быстрее. Производительность вопрос многогранный. Каким-то задачам важна равномерность операций, что бы вставка занимала фиксированное время, а не генерировала периодические спайки при копировании всех элементов массива. Для каких-то задач важно оптимальнео использование памяти, в arraylist можно выделить сразу массив огромного размера, что бы не происходило перевыделение памяти, но если размер массива сложно предугадать, то память будет использоваться не оптимально. К примеру вставка начало arraylist более медленная операция чем ставка в начало linkedlist.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html

И имутабельность и неблокарующее распаралеливание позволят больше сфоркусироваться на алгоритме чем на реализации и по факту приложение в целом будет работать быстрее. Хороший пример - это модель акторов. Подход можно назвать имутабельным по этому паттерну построен самый быстрые вэб сервер.
   MadHead
 
126 - 24.03.20 - 12:21
   cViper
 
127 - 24.03.20 - 13:19
(102) Вы сравниваете 2 алгоритма решающих разные задачи. В (90) он удаляет несколько значений, а не единичное. А в (56) единичное значчение. Попробуйте и переделайте свое решение для нескольких значений. И да, вы не умеете считать сложность алгоритмов.
(103) А что медленного в работе System.arrayCopy()? Он ведь по сути только создает новый массив и закидывает туда старые обьекты из старого массива.
(114) В TreeMap в основе также лежит дерево, самобаланчируемое красно-черное. Это классическая структура данных описанная во многих книгах по CS.
(117) Оно упорядочивает (сортирует) исходные данные и дает гарантированную сложность доступа O(log(n))
   Salimbek
 
128 - 24.03.20 - 13:20
(127) Ну держи... Смогешь быстрее?

    public static ArrayList<String> removeAll(ArrayList<String> z, int[] ii) {
        if(ii.length==0) return z;
        ArrayList<String> nz = new ArrayList<String>();
        Arrays.sort(ii);
        int prev=0;
        for (int x = 0; x < ii.length; x++ ) {
            if(ii[x]-prev>0)
                nz.addAll(z.subList(prev,ii[x]));
            prev=ii[x]+1;
        }
        if(prev<z.size()){
            nz.addAll(z.subList(prev,z.size()));
        }
        return nz;
    }
   cViper
 
129 - 24.03.20 - 13:22
(124) Ну да, "just in time" компиляция опимизирует все по-максимуму. Некоторые методы также переводятся в нативный код. В jvm hotspot для этого сделано 2 компилятора: client and server.
server компилятор может опитимизировать до нативного кода, в зависимости от того, как часто используется java метод.
   cViper
 
130 - 24.03.20 - 13:29
(128) Судя по всему я неправильно понял задачу. Думал у нас на входе коллекция со значениями которые надо удалить, а не с индексами. Код нечитаемый.
Если у нас на входе массив индексов и все значения в коллекции значений положительные, то вариант из (88) вполне рабочий и он будет быстрее чем (128).
 
 Рекламное место пустует
   fisher
 
131 - 24.03.20 - 13:47
(127) Не очень понял, к чему вы упомянули красно-черное дерево. Я, если что, в курсе как оно работает. Дерево, упомянутое для Vctor, ни разу на него не похоже. И именно поэтому я написал то, что написал.
   yavasya
 
132 - 24.03.20 - 13:47
(130) ты правильно понял задачу, ее остальные не могут понять, не знают что таблицу значений можно в ArrayList представить. Как можно удалить массив строк как в 1С?
   fisher
 
133 - 24.03.20 - 13:52
(131) Какая, в одно место, сортировка, если оно имутабельное? Не тупи, уже все дано разобрались зачем так сделано. Если бы ты больше читал, чем красовался знакомством с О-нотацией, то тоже бы разобрался.
   cViper
 
134 - 24.03.20 - 13:52
(131) Увидел что вы заинтересовались классом Vector. Как работает этот класс в Scala не знаю. Увидел комментарий про дерево. Решил порекомендовать , раз есть интерес.
   Salimbek
 
135 - 24.03.20 - 13:52
(132) Разъясните, пожалуйста, еще раз, для меня, как для особо тупого. У тебя в массиве _Значения_ (о чем пишет в (130)) или _Индексы_строк_ (как ты пишешь в (0))?
   cViper
 
136 - 24.03.20 - 13:54
(133) Предполагаю, что этот комментарий ко мне адресован. Я не знаю как работае ткласс Vector в Scala. Но могу предположить, что у него в конструкторе есть список входящих значений, которые он и сортирует при построении дерева.
   fisher
 
137 - 24.03.20 - 14:00
(136) Не надо предполагать. MadHead ранее уже все объяснил.
   sevod
 
138 - 24.03.20 - 14:01
(132)"... что таблицу значений можно в ArrayList представить."
Нельзя этого сделать. Учи азы. В ArrayList  нет колонок. Это массив. Если нужна пара ключ - значение в java, Map используй.
   Salimbek
 
139 - 24.03.20 - 14:03
(130) Вы вот серьезно в задаче "Имеется ArrayList и в массиве индексы строк (х.з. как полученных), которые надо удалить из этого ArrayList"
увидели "Имеется ArrayList положительных чисел и в массиве индексы строк (х.з. как полученных), надо добавлять знак '-' к числам в этих строках"?
   cViper
 
140 - 24.03.20 - 14:04
(137) Да , я уже погуглил. Меня немного сбил с толку ваш комментарий про перебалансировку.
   Salimbek
 
141 - 24.03.20 - 14:06
+ что касаемо читаемости кода - код, оптимизированный под производительность, будет чуть менее читаемым, с этим надо просто смириться.
   sevod
 
142 - 24.03.20 - 14:08
(141) если переменным дать человеческие название, компилятор тормозить начнет? :) Переменные надо по человечески называть.
   Кирпич
 
143 - 24.03.20 - 14:08
(132) Напиши на 1с, что ты хочешь сделать и покажи. Второй день выясняем, что тебе нужно, блин. :))
   Salimbek
 
144 - 24.03.20 - 14:16
(142) Там, в коде, введенные мной, переменные prev и nz. Я не думаю, что мне стоит их как-то еще переименовывать. Того, что есть - достаточно.
   yavasya
 
145 - 24.03.20 - 14:18
(135) строки как 1С
   yavasya
 
146 - 24.03.20 - 14:20
(138) уже надеюсь что тролишь, ты не понимаешь, а учишь. тащи пожарный гидрант для себя.
http://profi1c.ru/products/fba_toolkit/kratkiy-vvodnyiy-kurs-v-java-dlya-programmista-1s.html#h3_10    

public void testTable(){

//таблица значений
        ArrayList<Row> table = new ArrayList<Row>();

        //добавить строку
        Row row = new Row("Значение1 в первой строке", 1, 123.45);
        table.add(row);
        …
        …

}

/*
* Строка таблицы
*/
public static class Row {
        String field1;
        int field2;
        double field3;

        Row(String field1, int field2, double field3) {
                this.field1 = field1;
                this.field2 = field2;
                this.field3 = field3;
        }
}
   yavasya
 
147 - 24.03.20 - 14:21
(141) не вижу связи
   ДНН
 
148 - 24.03.20 - 14:27
удалил хоть, нет?
   Кирпич
 
149 - 24.03.20 - 14:46
(148) Я думаю, еще дня три :)
   sevod
 
150 - 24.03.20 - 15:18
(146) а ты кроме "таблица значений" и "ArrayList" в состоянии что либо в этом коде понять? :) Там не утверждают что "таблица значений" == "ArrayList", там ее эмулируют с использованием "ArrayList" и класса Row. Я понимаю, что на форуме 1С поголовно у всех развиты телепатические способности, но не до такой же степени :)
Ну запихни ты в class Row, поле int index, и оно не будет меняться при удалении. Если ты это искал. Только это не ArrayList, хоть он тут и используется.
(149) Оптимист :)
   Кирпич
 
151 - 24.03.20 - 15:21
(150) Интересно, как он в 1с удаляет пачками строки из таблицы значений. Такое вабще есть в 1с?
   Кирпич
 
152 - 24.03.20 - 15:23
Наркоман наверное. Что со страной сделали....
   Конструктор1С
 
153 - 24.03.20 - 15:59
(146) какая же это таблица значений? Если приближенно к 1с, это банальный массив структур получается
   MadHead
 
154 - 24.03.20 - 16:18
(153) Я за sorted set.
   Доктор Манхэттен
 
155 - 24.03.20 - 17:05
(105) >> В JS массивы - это скоере ассоциативный(индекс->значение) массив чем классический
C чего ты это взял?
   Доктор Манхэттен
 
156 - 24.03.20 - 17:14
(132) >> ты правильно понял задачу

Что??? Ты всю ветку писал что нужно удалить по значениям индексов, тут вдруг чел пишет что он думал что нужно удалить по значениям элементов, и ты пишешь что так и надо? Зачем же тогда столько времени всем голову морочил индексами? Это абсолютно разные задачи. Почему ты не можешь написать полное условие задачи, чтобы было проще тебе помочь?
   fisher
 
157 - 24.03.20 - 18:34
(146) Ну и покажи, как ты пробовал удалять по ссылке, что у тебя не получалось.
   Доктор Манхэттен
 
158 - 24.03.20 - 19:30
Похоже ТС сам тролль, и пришел сюда вовсе не за помощью, раз даже не желает поделиться условием задачи.
   sevod
 
159 - 24.03.20 - 20:49
(158)
Ну не, это же 1С форум. Тут же все телепаты :)
Шутки, шутками, но у меня уже давно привычка не читать внимательно ТЗ, не слушать внимательно пользователей. Опыт подсказывает, что все будет не так как они говорят/пишут. И если вдруг, о ужас, ты с нормальным человеком общаешься, то попадаешь в неприятную ситуацию.
   Asmody
 
160 - 24.03.20 - 21:03
(158) Не, он не тролль, это он Битрикс на java пишет: Аналог Битрикс 24 на Java
   v77
 
161 - 24.03.20 - 21:11
Понятно. Наркоман.
   cViper
 
162 - 24.03.20 - 22:16
(160) Кстати, задача интересная, только во тя бы использовал другой язык программирования (фреймворк) для этого.
   Asmody
 
163 - 24.03.20 - 22:18
(162) Пиши на Haskell.
   cViper
 
164 - 25.03.20 - 00:26
(163) Мне вот в голову приходят только RoR и Django
   Доктор Манхэттен
 
165 - 25.03.20 - 05:01
(164) Молодец, знаешь умные слова
   strange2007
 
166 - 25.03.20 - 08:28
(0) >> В 1С для этого создается массив строк для удаления, и далее в метод удалить куда передается массив строк
Это неэффективный метод. Лучше коллекцию обходить с конца и по условиям удалять нужные строки.
 
 Рекламное место пустует
   Salimbek
 
167 - 25.03.20 - 08:35
(166) Применительно к java - лучше делать как в (128)
   Кирпич
 
168 - 25.03.20 - 09:51
(167) Вот так будет проще, понятнее и памяти меньше жрать на больших списках. И по скорости будет не хуже (128)
    public static void removeAll(ArrayList<String> z, int[] ii) {
        if(ii.length==0) return;
        Arrays.sort(ii);
        for (int x = ii.length-1; x >= 0; x--) {
            z.remove(ii[x]);
        }       
    }

   Salimbek
 
169 - 25.03.20 - 09:58
(168) Уверен? Понимаешь как работает remove на массиве Array?
   Кирпич
 
170 - 25.03.20 - 10:00
(169) Уверен. Понимаю.
   fisher
 
171 - 25.03.20 - 10:05
(168) Уже проходили. Самый эффективный вариант - использовать метод removeIf. Туда параметром можно передать прям предикат с условием удаления "строки" и он имеет оптимизацию для удаления пачки строк. Т.е. "схлопывает" массив не после удаления каждой строки (как делает remove), а один раз при удалении всех строк попадающих под условие удаления.
   Кирпич
 
172 - 25.03.20 - 10:13
(171) верю. а в (128) точно пурга
   Кирпич
 
173 - 25.03.20 - 10:16
(171) а как этот предикат нарисовать, имея список индексов, которые удалить надо? я в java только со вчерашнего дня :)
   Salimbek
 
174 - 25.03.20 - 10:25
(172) Вот тебе код: https://pastebin.com/rhVcaNpk

Можешь или у себя или где в онлайн-компиляторах позапускать. Я на https://www.jdoodle.com/online-java-compiler/ попробовал 3 раза, выдало:

Kir:430090947
My : 17827987

Kir:410177305
My : 15280457

Kir:611930461
My : 25643564
   fisher
 
175 - 25.03.20 - 10:26
(172) Почему пурга? Там как раз избегание "схлопывания" по remove за счет выделения дополнительной памяти. Немутабельная функция, все дела :) В теории должно быть быстрее. На практике утверждать не готов. Библиотечные функции могут использовать довольно эффективные оптимизации. Надо тестить.
   Salimbek
 
176 - 25.03.20 - 10:26
(171) Код в (128) делает именно это.
   fisher
 
177 - 25.03.20 - 10:29
(173) Так я готов поспорить, что ТС изначально не требуется удаление по списку индексов. Зуб даю (на самом деле нет), что он этот список индексов получил обходом коллекции и проверкой того самого условия.
   fisher
 
178 - 25.03.20 - 10:32
(173) Для индексов тоже стопудово написать можно. Но "на гора" я его выдать не готов. Но было бы интересно сравнить производительность removeIf с (128)
   Salimbek
 
179 - 25.03.20 - 10:46
(178) Типа такого: https://pastebin.com/BXpsByP6

Код из (128) я оставил (заполняю массив удаляемых значениями 0, 3, 6, 9, ...)
А для removeIf использовал условие (i%3)==0 что, по сути, делает то же самое, результат трех запусков:

RIf:64474782
My :26406079

RIf:57740917
My :19147529

RIf:48343494
My :15319765

Хотя немного соврал, мой код удаляет 30000 элементов, а revoveIf - 33333. Массив переделал на заполнение тоже 33333 элементов:

RIf:73238044
My :40056951

RIf:56954746
My :23337888

RIf:46069908
My :19952359
   Кирпич
 
180 - 25.03.20 - 10:58
(174) И правда быстрее. Беру пургу обратно. Правда если удалять несколько элементов (штук десять), то (168) работает быстрее
   Кирпич
 
181 - 25.03.20 - 11:04
+(180) вот на таком например

int[] myArray = new int[] {119,5689,12478,456,10,2896,369};
   fisher
 
182 - 25.03.20 - 11:06
(180) В тесте Salimbek удаляет 30 тысяч из 100 тысяч :)
   fisher
 
183 - 25.03.20 - 11:06
А для нескольких элементов - да, накладные расходы могут перекрывать профит.
   Salimbek
 
184 - 25.03.20 - 11:48
(181) Вполне может быть, ведь "под капотом" remove, наверняка чистые блочные функции копирования данных. А в моем коде - addAll и z.subList() - вполне могут "вылетать" из блочного копирования.

+Посмотрел в OpenJDK / jdk8 / jdk8 / jdk - реализация addAll

        public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);
            int cSize = c.size();
            if (cSize==0)
                return false;


            checkForComodification();
            parent.addAll(parentOffset + index, c);
            this.modCount = parent.modCount;
            this.size += cSize;
            return true;
        }

т.е. отдается классу выше. Смотрим реализацию в AbstactList, а там
        for (E e : c) {
            add(index++, e);
            modified = true;
        }
т.е. тупое поэлементное добавление. Не удивительно, что работает не быстро.

И subList выполняет
return new SubList(

т.е. опять же происходит ненужное создание доп. массива.
Но уходить на уровени ниже для оптимизации производительности - лениво.
   MadHead
 
185 - 26.03.20 - 06:50
(179) А попробуйте поменять порядок запуска. Вначале ваш код, а потом уже сравниваемый. По крайней мере, если в IDEA выполнить последовательно 2 блока кода, то первый будет работать медленнее чем второй. Так как в начале "прогревается JVM"

В целом без требований к алгоритму удаления, сложно о чем-то говорить. Если нужно удалять большую часть, то лучше просто скопировать оставшиеся в новую коллекцию. Если удалять нужно мало элементов, то лучше итерироваться по коллекции с индексами для удаления. По умолчанию я бы написал что-то в духе (168)

        int[] toDelete = new int[]{1, 4, 2};
        ArrayList<Integer> list = Stream.of(1, 2, 3, 4, 5)
                .collect(Collectors.toCollection(ArrayList::new));

        Arrays.stream(toDelete)
                .boxed()
                .sorted(Collections.reverseOrder())
                .forEach((Integer i) -> list.remove(i.intValue()));

иначе - это преждевременная оптимизация.
   MadHead
 
186 - 26.03.20 - 06:52
(185) Работать на стримах будет медленнее, за то более модно )
   Salimbek
 
187 - 26.03.20 - 09:07
(186) На самом деле, там много различных влияющих факторов. Я ж побаловался потом еще немного с этой задачкой. В том числе сделал для себя вариант, когда начальный массив полностью выкидываем в обычный Array, а потом операциями блочного копирования собираем из него новый, не тратя время на оверхед в addAll и z.subList() На больших объемах удаляемых значений (ну типа удалить 30 000 из 100 000) и на мелких массивах (например удалить сколько-то из 1000 элементов) этот код работал быстрее, на каких-то размерах (например, удалить 200 из 100 000) - код с addAll выходил вперед, на каких-то простой remove быстрее отрабатывал (например удалить 10 из 30 000), зато этот remove вылетал по таймауту при попытке удалить 300 000 из 1 млн. элементов.
Причины такого поведения очень просты:
1) Потери кода с System.arrayCopy - идут на начальный переброс в массив всего списка, и, в конце, на переброс из этого массива обратно в ArrayList
2) Потери кода с addAll - идут на такое же неявное преобразование subList в Array и обратно, но тут меняются маленькие порции, и поэтому такой подход может быть быстрее, чем весь массив гонять туда-сюда, особенно, например, если удаляем 99 999 элементов из 100 000, в этом случае преобразование будет лишь у одного элемента, тогда как в коде 1) - весь массив будет дважды сконвертирован.
3) Потери кода с remove уходят на то, что для каждого удаляемого элемента создается копия всего массива (блочным копированием копируем часть данных _до_ удаляемого, и, потом, таким же блочным копированием копируем данные _после_, потом берем следующий элемент и повторяем. За счет прямого доступа к массиву - работаем очень быстро на малом количестве удаляемого). Но в случае с удалением 99 999 элементов из 100 000 - это будет полнейшей катастрофой.

Итого: самый оптимальный вариант - это создать свой класс-наследник от arrayList и внедрить туда алгоритм из 1) только без потерь на конвертацию. (потому как внутри все все равно лежит просто в массиве elementData, только извне доступа к нему нету).  Но это уже кун-фу более высокого порядка )))
   Конструктор1С
 
188 - 26.03.20 - 09:57
(179) сомнительная экономия. Ради выигрыша в сотые доли секунды, вместо использования библиотечного метода писать свой портяночный метод. К тому же, выиграв во времени выполнения, ты можешь проиграть в расходовании вычислительных ресурсов
   EVGA
 
189 - 26.03.20 - 11:05
(0) почему бы не так?
List<String> simpleList = Arrays.asList("test0", "test1", "test2", "test3", "test4", "test5");
simpleList.set(1, null);
simpleList.set(3, null);
simpleList.set(5, null);
simpleList.forEach(System.out::println);

вывод:
test0
null
test2
null
test4
null
   Salimbek
 
190 - 26.03.20 - 11:10
(188) Вы о чем речь ведете?
1) Какой имеется "библиотечный метод", чтобы мы могли его использовать? Или надо написать код _используя_ библиотечные методы?
2) "Выигрыш в сотые доли секунды" - на каких объемах данных? Вот я попробовал удалить стандартным remove в массиве из 1 000 000 элементов 700 000 - так ответа и не дождался. Код работал более 10 секунд и вывалился по таймауту (а ставить себе java для этого баловства мне лень).

(189) Наверное, потому, что надо именно удалить. Например, в Списке по условию могут быть и null-элементы (какая-нибудь выборка с БД с left_join). Или код завязан на количество строк, Или... да пофиг, что там еще...
   fisher
 
191 - 26.03.20 - 12:17
(179) Интересная инфа. Я думал, removeIf хуже себя поведет. А он вполне шустренько. Можно не заморачиваться в большинстве случаев.
   MadHead
 
192 - 27.03.20 - 02:41
(187) В развлекательных целях интересное и полезное занятие, но в реальных задачаx тяга к оптимальному мешает.
(190) Из библиотек подобные операции умеет делать pandas, numpy (к примеру удалять элементы коллекции по булевому массиву), наверняка в DL4J предоставляет подобный функционал и под джаву. То что не дождались ответа, скорее особенность онлайн компилятора, который может под капотом на калькуляторе работать, так как у меня на домашнем ноуте фильтрация массива.

Фильтрация стримом 80мс на моем ноуте.

        Set<Integer> toDelete = IntStream.range(1, 1500000)
            .boxed()
            .collect(Collectors.toSet());
        ArrayList<Integer> list = IntStream.range(1, 3000000)
            .boxed()
            .collect(Collectors.toCollection(ArrayList::new));

        long startTime = System.currentTimeMillis();
        ArrayList<Integer> filtered = list.stream().filter(toDelete::contains).collect(Collectors.toCollection(ArrayList::new));

        long timeTaken = System.currentTimeMillis() - startTime;
        System.out.println("Time taken: " + timeTaken + ", new size: " + filtered.size());
   cViper
 
193 - 27.03.20 - 04:01
(187) Зачем изобретать свой велосипед. Проше взять готовый опенсорс и использовать его.
(190) Если нет ограничений по памяти, то быстрее будет скопировать оставшиеся 300_000 элементов в новый список вместо удаления 700_000 из старого.
   cViper
 
194 - 27.03.20 - 04:04
(190) Скиньте код сюда, интересно.
   Конструктор1С
 
195 - 27.03.20 - 07:39
(190)
1. я имел ввиду, например, методы ArrayList
public boolean removeAll(Collection c)
public boolean removeIf(Predicate filter)
2. ну если много-много раз удалять через remove(int index) то конечно, можно и не дождаться. И вообще, если приходится таскать миллионы объектов в коллекциях, то это попахивает кривой архитектурой. Тут нужно думать не об написании своих методов с блэкджеком и шлюхами, взамен библиотечных, а о пересмотре архитектуры
   Salimbek
 
196 - 27.03.20 - 10:15
(195) И removeAll и removeIf работают со _значениями_ а надо было с _индексами_. Почему - не ко мне вопрос, я лишь баловался с алгоритмами.

(193) "быстрее будет скопировать оставшиеся 300_000 элементов в новый список" Дык, мой код как раз и делает именно это.

И вообще,  слишком много времени уже занимает это теоретическое исследование, без практического выхлопу ))) Поэтому далее тута общаться уже лень. Надеюсь, вы меня понимаете )))
   sevod
 
197 - 27.03.20 - 10:32
Тут уже Вася с форума удалился, а вы все еще никак ArrayList не можете :)
   MadHead
 
198 - 27.03.20 - 11:20
(197) Вероятнее всего автор сам себе выкрутил яйца заложенным подходом.
   fisher
 
199 - 27.03.20 - 18:56
(196) Я вот тоже поудивлялся. То ли cViper критиковал твой код в (128) даже не удосужившись его прочитать, то ли сетовал как раз на то, что он заточен на большую долю удаляемых элементов.
   yavasya
 
200 - 27.03.20 - 19:06
(197) я здесь дорогой) . это ты не можешь) не смог видимо стать программистом ООП, поэтому тебя бомбит от людей которые делают
  1  2  3   

Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.