![]() |
|
Java. Удалить в ArrayList массив строк. | ☑ | ||
---|---|---|---|---|
0
yavasya
23.03.20
✎
12:18
|
Допустим мне в ArrayList нужно удалить 1,3,5 строку. В 1С для этого создается массив строк для удаления, и далее в метод удалить куда передается массив строк. Как сделать такую операцию в джава чтобы индексы не сбивались ? Или остается строка с ссылкой null ?
|
|||
1
mikecool
23.03.20
✎
12:33
|
я не спец, но разве индексы останутся с пропусками после удаления?
|
|||
2
fisher
23.03.20
✎
12:35
|
(0) > "и далее в метод удалить куда передается массив строк"
Это где в 1С такое? |
|||
3
mikecool
23.03.20
✎
12:36
|
(2) это он с ТЗ попутал
|
|||
4
fisher
23.03.20
✎
12:37
|
ArrayList - это просто динамический массив (работающий на классическом массиве). Какие нафиг "строки"?
(3) И где такое в ТЗ? У меня устаревший СП, что ли? |
|||
5
dezss
23.03.20
✎
12:39
|
Ну так иди с конца массива, а не с начала.
|
|||
6
mikecool
23.03.20
✎
12:39
|
(4) а это уже я загнался ))
|
|||
7
Кирпич
23.03.20
✎
12:40
|
(0) Ну почитай help по ArrayList. Я вот почитал и вычитал, что можно удалять список объектов. Если у тебя в списке нет одинаковых объектов, то попробуй public boolean removeAll(Collection<?> c)
Если не устраивает, то используй HashMap какой нибудь или удаляй ручками с конца. |
|||
8
Кирпич
23.03.20
✎
12:42
|
+(7) да и вычислить индекс следующего удаляемого элемента ума много не надо
|
|||
9
fisher
23.03.20
✎
12:43
|
Я в джава не настоящий сварщик, но если тебе надо выборочно удалять элементы массива, то ArrayList плохой выбор. Он же там кажись при удалении элемента все остальные сдвигает. Физически. И ессно индексы сбиваются. Если по индексам, то как 1С надо - с конца.
|
|||
10
dezss
23.03.20
✎
12:46
|
(7) removeAll удаляет все объекты, которые передашь, вроде. Не по индексам.
|
|||
11
fisher
23.03.20
✎
12:56
|
(0) Ты же можешь удалять не по индексу, а по ссылке (как в ТЗ). Но если нужно много строк удалять, то дешевле запустить полный перебор и удалять в процессе (кажись итератор там поддерживает удаление).
Но нужно держать в уме, что удаление из ArrayList - относительно дорогая операция на больших массивах. Для тяжелых алгоритмов нужны альтернативные подходы или другие структуры данных. |
|||
12
fisher
23.03.20
✎
12:56
|
Тьфу, не строк - элементов.
|
|||
13
yavasya
23.03.20
✎
12:59
|
(11) очень интересно
|
|||
14
yavasya
23.03.20
✎
13:05
|
(4) ArrayList это таблица значений где каждая строка это многомерный массив
|
|||
15
Garikk
23.03.20
✎
13:07
|
(14) что там каждая строка? там каждая строка это ссылка на объект
|
|||
16
yavasya
23.03.20
✎
13:11
|
(15) а массив не ссылка?
|
|||
17
fisher
23.03.20
✎
13:11
|
(13) Три классические структуры данных:
ArrayList - динамический массив на непрерывных кусках памяти. Мгновенный доступ по индексу. Дорого удалять. Неравномерная стоимость добавления (когда кончается место - выделяется новый кусок побольше и в него копируется старый). LinkedList - динамический массив на двусвязанном списке. Дорого доступаться по индексу, зато мгновенное удаление и добавление. Жрет больше памяти. HashMap - мгновенный доступ по ключу. Нет доступа по индексу. Удаление через зануление. Проблемы с добавлением примерно такие же как у ArrayList. (14) Нет. Это просто одномерный массив. Но если засунешь в качестве элементов другие ArrayList, то будет некий аналог таблицы значений. |
|||
18
ИУБиПовиц
23.03.20
✎
13:12
|
А через iterator(). hasNext ().remove если попробовать? индексы тоже перестраиваются?
|
|||
19
fisher
23.03.20
✎
13:14
|
(18) Конечно перестраиваются. Удаление через итератор (если поддерживается) гарантирует просто что перебор по итератору при удалении не собъется.
|
|||
20
yavasya
23.03.20
✎
13:14
|
(18) да там два пути, итератор перестраивать на +2 после удаления , и с конца перебирать. хотел по ссылке, но это невозможно
|
|||
21
yavasya
23.03.20
✎
13:16
|
(19) а что останется после удаления ? удалили строку, итератор не сбился, что осталось?
|
|||
22
fisher
23.03.20
✎
13:20
|
(21) Останется ГДЕ? В массиве ничего не останется. Если получил ссылку на объект по итератору, то она никуда не денется. Ты же просто удалил элемент массива, а не объект ссылка на который там лежала.
|
|||
23
yavasya
23.03.20
✎
13:24
|
(21) ну смотри , массив 0,1,2,3,4
удалил 2 и 4 элемент , остается 0,2,4. при переборе массива какая конструкция идет 0, null, 2,null,4 ? как индексы сохранить ? |
|||
24
fisher
23.03.20
✎
13:29
|
(23) В жаве в ArrayList ты не можешь засунуть int (примитивный тип). Только объекты Integer (ссылочный тип-обертка). Т.е. ArrayList будет содержать ссылки на объекты Integer.
Если удалишь сначала 4 элемент по индексу а затем второй, то в массиве останется 0,2,4 и тоже самое будет выдавать при переборе. Но если при переборе ты в какой-то переменной сохранял ссылки на 1 и 3, то они останутся доступны (объекты живут, пока на них есть ссылки, как и в 1С). Если хочешь чтобы индексы остались и были null, тогда тебе не удалять надо а просто присваивать нужным элементам null явно. Получишь разряженный массив. |
|||
25
Salimbek
23.03.20
✎
13:31
|
(23) Какие "индексы" сохранить и куда? У вас где-то в других местах хранятся эти самые "индексы"? Если да, то ответ очевиден, вам ничего удалять нельзя. Можно, например, ставить своеобразную "пометку удаления".
|
|||
26
yavasya
23.03.20
✎
13:38
|
(25) я имел ввиду что если индексы не сбиваются, значит ссылки на строки остаются
|
|||
27
yavasya
23.03.20
✎
13:39
|
(24) Если удалишь сначала 4 элемент по индексу а затем второй, то в массиве останется 0,2,4 и тоже самое будет выдавать при переборе. а как ты оставишь тож самое при переборе ? remove в конце перебора вызвать?
|
|||
28
Garykom
гуру
23.03.20
✎
13:41
|
(0) Никогда не удаляй строки - всегда создавай новый "список" и переноси туда только нужные строки, которые "надо оставить".
|
|||
29
Salimbek
23.03.20
✎
13:41
|
(26) Еще раз, вы упорно делаете акцент на "индексы", я и спрашиваю - для чего вам это?
|
|||
30
Salimbek
23.03.20
✎
13:42
|
(28) Это может быть довольно дорогой операцией.
|
|||
31
yavasya
23.03.20
✎
13:42
|
(29) если индексы собьются при удалении, то нельзя по ним получать строки
|
|||
32
Garykom
гуру
23.03.20
✎
13:44
|
(30) Это удаление строки в цикле дорогая операция, когда на каждом шаге цикла новый объект пересоздается платформой и туда строки переносятся.
|
|||
33
Salimbek
23.03.20
✎
13:45
|
(31) Если вы строку удалили, то какую строку по этому удаленному индексу вы хотите получить?
|
|||
34
Garikk
23.03.20
✎
13:45
|
(32) если в массиве 20гб данных, пересоздавать массив будет пипец как дорого, проще реально строки циклом удалять
|
|||
35
Salimbek
23.03.20
✎
13:47
|
(34) Согласен, только еще эффективнее использовать динамически связанные структуры. Т.к. при простом удалении как раз и будет каждый раз пересоздаваться "массив 20гб данных"
|
|||
36
yavasya
23.03.20
✎
13:48
|
(33) у меня складывается впечатление вы читаете с конца, поэтому ничего не понятно
|
|||
37
Кирпич
23.03.20
✎
13:50
|
(0)Так надо?
На Java первый раз в жизни пишу :)
|
|||
38
yavasya
23.03.20
✎
13:51
|
(37) я тоже так могу копировать код с форумов. ищу оптимальное решение
|
|||
39
Кирпич
23.03.20
✎
13:52
|
(38) я не копировал. я сам.
|
|||
40
yavasya
23.03.20
✎
13:54
|
(39) ты ж в первый раз в жизни видишь
|
|||
41
fisher
23.03.20
✎
13:56
|
(36) Я читаю с начала и тоже нифига не понимаю.
|
|||
42
Кирпич
23.03.20
✎
13:57
|
(40) ПИШУ, а не ВИЖУ
|
|||
43
Salimbek
23.03.20
✎
13:57
|
(36) Я читаю тему с самого начала, и если вам непонятен мой вопрос, то:
1) "В 1С для этого создается массив строк для удаления, и далее в метод удалить куда передается массив строк." - где вы такое нашли? А если этого нету, то для чего выдумывать несуществующие сущности? 2) "Как сделать такую операцию в джава чтобы индексы не сбивались ? " - Вот тут вот - для чего вам тут нужны некие "индексы", и чтобы они "не сбивались"? 3) "Или остается строка с ссылкой null ?" - если вы строку удалили, то null не будет. |
|||
44
Кирпич
23.03.20
✎
14:06
|
(43) Мне кажется он хотел удалять из списка элементы не по одному, а несколько сразу.
Типа вот список {000,100,200,300,400,500,600} отсчет с нуля удалить надо [1,3,5] Получаем {000,200,400,600} |
|||
45
Кирпич
23.03.20
✎
14:07
|
(40) Так или не так?
|
|||
46
yavasya
23.03.20
✎
14:12
|
(45) все верно
|
|||
47
yavasya
23.03.20
✎
14:16
|
(43) 1) "В 1С для этого создается массив строк для удаления, и далее в метод удалить куда передается массив строк." - где вы такое нашли? А если этого нету, то для чего выдумывать несуществующие сущности? Вы тролите ? С таблицами значений не работали ?
2) "Как сделать такую операцию в джава чтобы индексы не сбивались ? не прочитали ничего 3) "Или остается строка с ссылкой null ?" - если вы строку удалили, то null не будет. Это ваше сугоболичное не начем не основанное убеждение |
|||
48
Кирпич
23.03.20
✎
14:16
|
(46) Ну вот тебе решение в (37)
Но лучше использовать HashMap вместо ArrayList |
|||
49
yavasya
23.03.20
✎
14:18
|
(48) видимо так . или по значению строки удалять
|
|||
50
Salimbek
23.03.20
✎
14:19
|
(45) Тогда в вашем коде из (37) надо немного не так:
for (int x = 0; x < ii.length; x++ ) поменять на: for (int x = ii.length-1; x >=0 ; x-- ) и всякие танцы с xx - убрать. Еще бы желательно сделать проверку на возможные дубли в ii, чтобы случайно за пределы массива не вывалиться. (46) Самый эффективный вариант вам уже сказали - делать копию массива и туда переносить элементы из первого, за исключением тех, кто в вашем списке. При этом можно будет использовать команды копирования блоков данных, которые очень эффективно компилируются. |
|||
51
yavasya
23.03.20
✎
14:22
|
(50) перебрать с конца уже было.
амый эффективный вариант вам уже сказали - делать копию массива и туда переносить элементы из первого, за исключением тех, кто в вашем списке. При этом можно будет использовать команды копирования блоков данных, которые очень эффективно компилируются. Здесь я с вами соглашусь. |
|||
52
fisher
23.03.20
✎
14:24
|
Вообще лучше всего использовать removeIf и туда засунуть предикат условия на удаление.
Так хотя бы "схлопывание" массива будет выполнено за один присест. |
|||
53
Конструктор1С
23.03.20
✎
14:26
|
(0) а как ты пришел к тому, что тебе нужно удалить конкретные индексы? Правильнее всё-таки удалять объекты. И если ты получил индексы, то где-то чуть раньше работал с объектами
|
|||
54
Dionis Sergeevich
23.03.20
✎
14:28
|
Это форум про аниме? Как пропатчить кде под фрибсд?))
|
|||
55
yavasya
23.03.20
✎
14:29
|
(53) если удалишь строку, то поплывут индексы. Про это.
|
|||
56
Salimbek
23.03.20
✎
14:30
|
(47) 1) "Вы тролите ? С таблицами значений не работали ?" - Вовсе нет, работал. Метода "Удалить" с передачей внутрь массива - ни разу не сталкивался. Ни у массива тут: https://helpme1c.ru/massivy-v-yazyke-1s-8-v-primerax ни у Таблицы значений тут: https://helpme1c.ru/tablica-znachenij-v-yazyke-1s-8-v-primerax Везде "Удалить(Индекс)"
3) Х.з. как там в Ява, но в С++ вообще нельзя удалить элемент массива, поэтому придумывают велосипеды, типа: https://ru.stackoverflow.com/questions/168764/%d0%a3%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%8d%d0%bb%d0%b5%d0%bc%d0%b5%d0%bd%d1%82%d0%b0-%d0%bc%d0%b0%d1%81%d1%81%d0%b8%d0%b2%d0%b0-%d0%bf%d0%be-%d0%b8%d0%bd%d0%b4%d0%b5%d0%ba%d1%81%d1%83 "Судя по всему, много элементов удалять не придётся, а потому просто смещаете все элементы, кроме удаляемого, на 1 влево и уменьшаете длину массива на 1." k - нужный индекс for (long i = k; i < n-1; ++i) { a[i] = a[i + 1]; } --n; Можно переделать этот алгоритм и на множество элементов. |
|||
57
fisher
23.03.20
✎
14:32
|
(53) Насколько я понял, он хотел по аналогии с удалением строк таблицы значений по ссылкам сделать (в сабже он про это писал). Но запутался в своей эмуляции ТЗ на вложенных списках, не смог этого сделать и попытался через индексы. А то, что можно прямо в процедуру удаления передать ссылку на функцию с условием удаления он догадаться не смог, потому что в 1С таких вариантов нет.
|
|||
58
yavasya
23.03.20
✎
14:37
|
(57) блин, да это легко написать. я не знаю как правильно
|
|||
59
yavasya
23.03.20
✎
14:39
|
(56) ну да, это с конца способ перебрать
|
|||
60
yavasya
23.03.20
✎
14:42
|
(57) прямо в процедуру удаления передать ссылку на функцию с условием удаления. а это как ?
|
|||
61
Salimbek
23.03.20
✎
14:43
|
(59) Вы внимательно уловили суть этого алгоритма? Там нету ни удаления, ни перебора с конца.
|
|||
62
yavasya
23.03.20
✎
14:46
|
(61) сделать копию массива и туда переносить элементы из первого, за исключением тех, кто в вашем списке.
|
|||
63
yavasya
23.03.20
✎
14:46
|
(61) там нативная библиотека и она очень быстро работает
|
|||
64
fisher
23.03.20
✎
14:48
|
(60) См. (52)
|
|||
65
Salimbek
23.03.20
✎
14:49
|
(60) Это:
public static void removeAll(ArrayList<String> z, int[] ii) { Arrays.sort(ii); z.removeIf(el -> (Arrays.binarySearch(ii, el) >= 0)); } |
|||
66
yavasya
23.03.20
✎
14:51
|
(65) ты ооп пишешь ? лямда выражение массивы, бинарные деревья
|
|||
67
Salimbek
23.03.20
✎
14:51
|
(62) ну почти, только копии массива не создается, а текущие элементы переписываются
|
|||
68
Salimbek
23.03.20
✎
14:52
|
(66) Ты у меня на счет кода (65) спрашиваешь или вообще?
|
|||
69
yavasya
23.03.20
✎
14:52
|
вообще
|
|||
70
fisher
23.03.20
✎
14:54
|
(65) Я подозреваю, что к списку индексов для удаления он пришел от безысходности. И в лямбде ему нужно просто свое условие прописать.
Но вариант красивый. Чувствуется практический опыт в java :) |
|||
71
fisher
23.03.20
✎
14:59
|
(66) Arrays.binarySearch - это аналог Найти() в массиве 1С. А лямбды в java - это просто синтаксический сахар вокруг объектов. Просто чтобы писанины было меньше.
|
|||
72
Salimbek
23.03.20
✎
14:59
|
(69) Вообще пишу на том, на чем удобно
(70) "Чувствуется практический опыт в java :)" - у меня есть опыт с замыканиями в Ruby и немного C++, конструкцию removeIf - подсказал ты, быстрый поиск элемента в массиве нашел в гугле. И вуаля, я уже гуру в java :-) |
|||
73
yavasya
23.03.20
✎
15:01
|
(72) ясно. только начал ооп изучать, даже ты пока гуру)
|
|||
74
yavasya
23.03.20
✎
15:03
|
(72)далеко не факт что правильно . тролишь ты профессионально)
|
|||
75
fisher
23.03.20
✎
15:04
|
(72) Ну дык. Иллюстрация к тому, что хорошему прогу пофиг на чем писать. И что, джавовую лямбду за минуту нарисовал исключительно из опыта замыканий в руби? Собака подозревака. Они в джава специфические.
|
|||
76
Salimbek
23.03.20
✎
15:05
|
(74) Если ты внимательно прочитаешь мои посты, то поймешь, что я никого не троллю. Я серьезно пытался понять, нахрена тебе обязательное сохранение индексов.
Кстати - в (65) ошибка, не делай так :-((( Там ищется элемент массива, а тебе нужон именно индекс... |
|||
77
Salimbek
23.03.20
✎
15:07
|
+(76) Особо отмечу, что условия "проход за один цикл" в операторе removeIf нет.
|
|||
78
fisher
23.03.20
✎
15:14
|
(76) По-моему, оно не скомпилируется. Arrays.binarySearch(ii, el) - туда ii само в тело предиката не прилетит как в функциональных языках.
|
|||
79
fisher
23.03.20
✎
15:20
|
А может и прилетит, если лямбды в сабклассы разворачиваются... Давно пытался в это погрузиться - забросил. Не помню уже, не слушайте меня :)
|
|||
80
Salimbek
23.03.20
✎
15:31
|
(78) Там проблема в другом, там в (ii, el) - el - это элемент массива z, т.е. строка. А нужен Индекс.
Вообще выгоднее в элементах этого самого ArrayList сделать еще одно поле, типа isDeleted boolean, которое потом проставить на удаляемых элементах в true или на нарисованной форме, или пробежавшись по массиву индексов. А уже затем z.removeIf(el -> el.isDeleted) ну или как оно там к полям коллекции обращается... |
|||
81
fisher
23.03.20
✎
15:38
|
(80) Чем выгоднее? Почему в предикате не проверять все что надо? Разве что для повышения читабельности, если там совсем что-то хитровымученное.
|
|||
82
Salimbek
23.03.20
✎
15:44
|
(81) Выгоднее, например, тем, что isDeleted можно и в графической форме дать юзеру проставлять, да и вообще, isDeleted это как раз по 1С-ному ))) А так - согласен, чем меньше беготни по массиву, тем быстрее все работает.
|
|||
83
Доктор Манхэттен
23.03.20
✎
16:59
|
(0) Если в массиве важны индексы, то это явный признак того, что массив используете не по назначению. Индексы массива не должны нести никакой смысловой нагрузки. При правильно спроектированном коде, индексы не используются в принципе.
|
|||
84
MadHead
23.03.20
✎
18:32
|
Всю ветку не читал.
По классике правильнее всего удалить через итератор (понадобиться переменная которая определяет четный/не четный) |
|||
85
Доктор Манхэттен
23.03.20
✎
22:06
|
(0) В чем вообще суть задачи? По какому условию нужно удалять элементы, и для чего впоследствии нужны индексы? Напиши полностью что ты хочешь сделать.
|
|||
86
cViper
23.03.20
✎
22:20
|
(0) Используй массив вместо листа.
|
|||
87
cViper
23.03.20
✎
22:30
|
(14) ArrayList - это реализация интерфейса List на базе массива.
А то что таблица значений, это либо HashMap либо просто ArrayList<ArrayList<String>> либо String[][], смотря что тебе надо. (37) Лучше бы не писал *) (0) Положи в HashSet значения которые надо удалить. Итерирую массив значений проверяй if(set.contains(value)) то переписывай значение мссива на null. |
|||
88
cViper
23.03.20
✎
22:35
|
(0) Еще, как вариант, если в твоем листе только положительные числа, то модешь им добавлять знак -. Тогда и ндексы сохранишь и значения предыдущие будут.
|
|||
89
MadHead
23.03.20
✎
22:39
|
Если я понял правильно то нужно удалить нечетные элементы
List<Integer> list = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList()); Iterator<Integer> iter = list.iterator(); boolean isOdd = false; while (iter.hasNext()) { iter.next(); if (isOdd) { iter.remove(); } isOdd = !isOdd; } list.forEach(System.out::println); Если стараться придерживаться более функционального стиля, то можно сделать без сайдэффектов преобразовать List элементов в Stream [index, value] и применить фильтр. |
|||
90
cViper
23.03.20
✎
22:40
|
(71) не знаю как работает Найти в 1С, но binarySearch это стандартынй алгоритм бинарного поиска ,который работает только на отсортированных данных. Что касается стримов, то они еще и медленне работают чем простые циклы.
(65) Неоптимальное решение. Cортировка будет за O(n*log(n))(каждый бинарный поиск буде за O(log(n)), но им можно пренебречь). в (87) решение работает за O(n) |
|||
91
Сияющий в темноте
23.03.20
✎
23:01
|
ArrayList это просто массив,если из егг середины удаляется элемент,то остальные просто сдвигаются
при удалении с конца будет немного меньше сдвигов. просто,если порядок элементов не важен,то,обычно,в дыру после удаления пихают последний элемент-это очень быстро,но часто дает очень странный результат. |
|||
92
Сияющий в темноте
23.03.20
✎
23:04
|
и еще у java нет возможности изменчть выделенный блок памяти,поэтому,ввделив 16 элементов и кдалив что-то мы получим пустые ссылки в конце,так как стстема для уиеньшения массива не будет его копировать.
и не забываем,что в тех языках,где есть перевыделение памяти,это очень критичная к производительности операция,так как требует выполнения копирования блокп данных. |
|||
93
Доктор Манхэттен
23.03.20
✎
23:17
|
(89) >> Если я понял правильно то нужно удалить нечетные элементы
Очень сомневаюсь что задача стоит именно так. Представьте, приходит тетя Глаша из Бухгалтерии, и говорит: "Мне тут прислали имейл с ArrayList, нужно из него удалить все нечетные элементы". |
|||
94
MadHead
23.03.20
✎
23:24
|
(93) Это довольно частый вопрос на собесах и синтетических задачах.
К примеру можно представить, что нужно получить часть данных или алгоритм игры требует такого удаления. |
|||
95
MadHead
23.03.20
✎
23:25
|
(92) у ArrayList есть метод trimToSize
|
|||
96
Доктор Манхэттен
23.03.20
✎
23:39
|
(94) Пока ТС молчит, непонятно это действительно синтетическая задача, или он придумал неоптимальное решение для реальной задачи, и теперь пытается вставить в него костыли.
|
|||
97
Доктор Манхэттен
23.03.20
✎
23:55
|
(94) Если бы это был JS, я бы написал просто фильтр нечетных:
return [0, 1, 2, 3, 4].filter((_, i) => i & 1); Думаю в Java наверняка есть аналог такой функции. |
|||
99
cViper
24.03.20
✎
02:15
|
(92) При расширении или сужении массива никакого копирования не проиходит. Просто обьекты переносятся в массив нового размера. Эта процедура очень быстрая, выполняется нативный код System.arrayCopy. А старый обьект массива удалится сборщиком мусора.
|
|||
100
Конструктор1С
24.03.20
✎
03:42
|
(55) обычно индексы массива интересуют только сам массив. А если не только сам массив, то это кривой алгоритм
|
|||
101
Конструктор1С
24.03.20
✎
03:49
|
(96) это может быть академическая задача из курса по программированию или учебника какого. Академические задачки по программированию часто отличаются бессмысленностью и беспощадностью
|
|||
102
Salimbek
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,и никто не понимает,что случилось. |
|||
104
yavasya
24.03.20
✎
10:12
|
(103) да, потому что нативный метод, а jvm не умеет работать с памятью так же хорошо как c++ .
|
|||
105
MadHead
24.03.20
✎
10:39
|
(97) В JS массивы - это скоере ассоциативный(индекс->значение) массив чем классический, сравнение не очень корреткное. То есть в джаве нужно вручную создать пары индекс-значение после чего уже можно преобразовать коллекцию в stream и применить фильтр. Есть либы которые реализовую метод zipWithIndex.
(99) При увеличении точно происходит копирование в новую область большего рамера и при уменьшении скорее всего тоже. (103) Копирование массива операция относительно быстрая, соизмеримая с подобной операцией в C/C++ но сложность операции O(N). В принципе сложность описывает как зависит время выполнения от ко-ва элементов и не говорит ничего о реальном времени выполнения. Если размер коллекции сильно меняется, то есть более оптимальные структуры для хранения таких данных. В Скале на пример есть Vector который по сути явялется деревом с массивами в узлах размерностью 32элемента. Это позволяет совместить плюсы linkedlist и arraylist. Большой плюс, что такая коллекция оптимально использует кэш процессора при итерации, так как 32-х разрядные массивы помещаются в кэш линию |
|||
106
fisher
24.03.20
✎
10:53
|
(103) Копирование с помощью System.arrayCopy - относительно быстрое даже на больших объемах. Насколько я понимаю, под капотом оно использует команды процессора блочного копирования памяти или что-то в этом духе. Встречал на просторах сравнение с обычным поэлементным копированием и копированием через этот метод - разница больше чем на порядок. Типа миллион элементов где-то 200 мс поэлементно у кого-то заняло, а этой хренью то ли за 10, то ли за 15 мс скопировало. Понятно, что голову все равно включать надо. Но все равно ArrayList остается самой универсальной реализацией динамического массива.
|
|||
107
fisher
24.03.20
✎
10:57
|
А удалять или занулять элементы - это тоже всегда компромисс и решается по месту. Если массив не слишком большой - лучше удалять. Тем более, что removeIf делает это оптимизированно. Обслуживать разряженный массив - тоже не фунт изюму и легко может в итоге привести к неожиданным сайд-эффектам.
|
|||
108
sevod
24.03.20
✎
11:04
|
Хочешь на Java-велосипед, колеса невообразимой формы? Зайди на 1С форум!
Вася, не удаляй из ArreyList ничего, ты еще не дорос до такого сверх высокого уровня. Ведь для этого нужно прочитать что такое ArreyList, а так же ознакомиться с другими коллекциями Java. Это ведь целый 8-ой уровень JavaRush (когда то до 10 было бесплатно, сейчас не знаю). Вася, забудь слово ООП. Учи с начала. Возьми какой нибудь готовый курс и с нуля. Последовательно. Без пропусков. Смещение индексов в ArreyList при добавлении/удалении элементов, это то, ради чего его и создавали. А ты с этим зачем то борешься. Для того что бы это понять, нужно сравнивать с Arrey. Но ведь для того, что бы это понять, придется почитать об этом. Методом тыка может не прокатить. |
|||
109
yavasya
24.03.20
✎
11:07
|
(108) качественный троль
|
|||
110
sevod
24.03.20
✎
11:09
|
(109) это был лучший ответ в этой ветке. У меня чуть пукан не разорвало когда я это все читал. И я реально на 8 лвл javarush и там реально проходят коллекции.
Тебе реально рано с массивами работать, учи с нуля! |
|||
111
yavasya
24.03.20
✎
11:10
|
(108) я кстати на курсе программирования, то что сделать можно и как сделать я знаю. основных вопрос 1. Как сделать правильно и оптимально
|
|||
112
yavasya
24.03.20
✎
11:11
|
(110) ну и на каком уровне там разбираются? удалил элемент и молодец? умничай для себя . не буду кормить тролей
|
|||
113
sevod
24.03.20
✎
11:12
|
(111) а чего ты тогда основ не знаешь? и главное, почему ты этот вопрос на своем курсе не задал?!
|
|||
114
fisher
24.03.20
✎
11:13
|
(105) Пошел почитать за класс Vector. Жутко было интересно, как же они перебалансируют дерево при удалениях/добавлениях. А оно иммьютбл. Ыыыыыы :)
|
|||
115
antgrom
24.03.20
✎
11:15
|
(110) 8 уровень javarush это невысокий уровень. Любой 1Сник пройдёт легко, без предварительных знаний java. Нужно только время - несколько дней.
|
|||
116
sevod
24.03.20
✎
11:19
|
(115) а я о чем? это околонулевой. Поэтому и пишу на полном серьезе что бы начал с нуля. Если прочитает что такое ArrayList и просто Array, то поймет какой он вопрос задал.
|
|||
117
fisher
24.03.20
✎
11:20
|
(105) Я теперь вообще не понимаю, нахрена там внутри дерево, если оно иммьютбл. Что это дает в сравнении с обычным иммьютбл-массивом? Где про это почитать можно?
|
|||
118
sevod
24.03.20
✎
11:24
|
(117) скорее всего для совместимости оставили. Что бы древний код не помер. Загугли по этому дереву, если попадешь на оф. документацию, возможно где то на странице будет рекомендованные на данный момент методы.
Там много таких. К примеру Date тоже лучше не использовать. |
|||
119
fisher
24.03.20
✎
11:26
|
(118) Речь про Scala
|
|||
120
fisher
24.03.20
✎
11:30
|
(105) Могу только предположить, что это позволяет делать хитрые оптимизации при операциях над векторами. Чтобы не копировать неизменные блоки, уменьшая общее количество копирований.
|
|||
121
MadHead
24.03.20
✎
11:35
|
(117) Имьютабл в прицепе функциональный подход - это по максимум отказаться от мутабельных объектов. Но оверхед не такой большой, так как при копировании сами массивы не пересоздаются. И отсуствие сайд эффектов позволяет обрабатыват коллекции многопоточно без синхронизации.
К примеру есть коллекция содержащий 320 элементов - это 10 массивов по 32 элемента для vector или массив 320элементов. 1a. При добавлении элемента в vector скопируется 10 ссылок + выделиться дополнительный массив размером 32 1b. При добавлении элемента в массив будет выделена область памяти под все данныее нового размера, а старые будут удалены. |
|||
122
MadHead
24.03.20
✎
11:39
|
(120) Массив даст все те же приемущества в плане векторных вычислений. Что бы быть на одной странице поясню, что я имею в виду под векторными вычислениями.
Современные процессоры подддерживают векторыне операции - то есть позволяют сделать 8 и более арифметических однотипных операция за одину операцию. Это дает существенный прирост в производительности CPU операций (активно используется в pandas и Apache arrow) |
|||
123
fisher
24.03.20
✎
11:50
|
(121) Идея понятна. Прикольно. В среднем ArrayList будет быстрее. Зато тут иммьютбл со всеми своими плюшками и одинаковое время выполнения операций без внезапных просадок.
|
|||
124
Конструктор1С
24.03.20
✎
12:03
|
(104) "jvm не умеет работать с памятью так же хорошо как c++"
Ты сильно заблуждаешься. Так было лет 20 назад. Современная джавамашина сама умеет хитро оптимизировать код, к тому же позволяет произвести тонкую настройку. На плюсах можно написать более производительный код, но для этого требуется: а) высокая квалификация плюсника б) дофига времени в 99% случаев овчинка выделки не стоит |
|||
125
MadHead
24.03.20
✎
12:21
|
(123) Если брать среднюю температуру по больнице, то можно сказать что в среднем arraylist быстрее. Производительность вопрос многогранный. Каким-то задачам важна равномерность операций, что бы вставка занимала фиксированное время, а не генерировала периодические спайки при копировании всех элементов массива. Для каких-то задач важно оптимальнео использование памяти, в arraylist можно выделить сразу массив огромного размера, что бы не происходило перевыделение памяти, но если размер массива сложно предугадать, то память будет использоваться не оптимально. К примеру вставка начало arraylist более медленная операция чем ставка в начало linkedlist.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html И имутабельность и неблокарующее распаралеливание позволят больше сфоркусироваться на алгоритме чем на реализации и по факту приложение в целом будет работать быстрее. Хороший пример - это модель акторов. Подход можно назвать имутабельным по этому паттерну построен самый быстрые вэб сервер. |
|||
126
MadHead
24.03.20
✎
12:21
|
||||
127
cViper
24.03.20
✎
13:19
|
(102) Вы сравниваете 2 алгоритма решающих разные задачи. В (90) он удаляет несколько значений, а не единичное. А в (56) единичное значчение. Попробуйте и переделайте свое решение для нескольких значений. И да, вы не умеете считать сложность алгоритмов.
(103) А что медленного в работе System.arrayCopy()? Он ведь по сути только создает новый массив и закидывает туда старые обьекты из старого массива. (114) В TreeMap в основе также лежит дерево, самобаланчируемое красно-черное. Это классическая структура данных описанная во многих книгах по CS. (117) Оно упорядочивает (сортирует) исходные данные и дает гарантированную сложность доступа O(log(n)) |
|||
128
Salimbek
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; } |
|||
129
cViper
24.03.20
✎
13:22
|
(124) Ну да, "just in time" компиляция опимизирует все по-максимуму. Некоторые методы также переводятся в нативный код. В jvm hotspot для этого сделано 2 компилятора: client and server.
server компилятор может опитимизировать до нативного кода, в зависимости от того, как часто используется java метод. |
|||
130
cViper
24.03.20
✎
13:29
|
(128) Судя по всему я неправильно понял задачу. Думал у нас на входе коллекция со значениями которые надо удалить, а не с индексами. Код нечитаемый.
Если у нас на входе массив индексов и все значения в коллекции значений положительные, то вариант из (88) вполне рабочий и он будет быстрее чем (128). |
|||
131
fisher
24.03.20
✎
13:47
|
(127) Не очень понял, к чему вы упомянули красно-черное дерево. Я, если что, в курсе как оно работает. Дерево, упомянутое для Vctor, ни разу на него не похоже. И именно поэтому я написал то, что написал.
|
|||
132
yavasya
24.03.20
✎
13:47
|
(130) ты правильно понял задачу, ее остальные не могут понять, не знают что таблицу значений можно в ArrayList представить. Как можно удалить массив строк как в 1С?
|
|||
133
fisher
24.03.20
✎
13:52
|
(131) Какая, в одно место, сортировка, если оно имутабельное? Не тупи, уже все дано разобрались зачем так сделано. Если бы ты больше читал, чем красовался знакомством с О-нотацией, то тоже бы разобрался.
|
|||
134
cViper
24.03.20
✎
13:52
|
(131) Увидел что вы заинтересовались классом Vector. Как работает этот класс в Scala не знаю. Увидел комментарий про дерево. Решил порекомендовать , раз есть интерес.
|
|||
135
Salimbek
24.03.20
✎
13:52
|
(132) Разъясните, пожалуйста, еще раз, для меня, как для особо тупого. У тебя в массиве _Значения_ (о чем пишет в (130)) или _Индексы_строк_ (как ты пишешь в (0))?
|
|||
136
cViper
24.03.20
✎
13:54
|
(133) Предполагаю, что этот комментарий ко мне адресован. Я не знаю как работае ткласс Vector в Scala. Но могу предположить, что у него в конструкторе есть список входящих значений, которые он и сортирует при построении дерева.
|
|||
137
fisher
24.03.20
✎
14:00
|
(136) Не надо предполагать. MadHead ранее уже все объяснил.
|
|||
138
sevod
24.03.20
✎
14:01
|
(132)"... что таблицу значений можно в ArrayList представить."
Нельзя этого сделать. Учи азы. В ArrayList нет колонок. Это массив. Если нужна пара ключ - значение в java, Map используй. |
|||
139
Salimbek
24.03.20
✎
14:03
|
(130) Вы вот серьезно в задаче "Имеется ArrayList и в массиве индексы строк (х.з. как полученных), которые надо удалить из этого ArrayList"
увидели "Имеется ArrayList положительных чисел и в массиве индексы строк (х.з. как полученных), надо добавлять знак '-' к числам в этих строках"? |
|||
140
cViper
24.03.20
✎
14:04
|
(137) Да , я уже погуглил. Меня немного сбил с толку ваш комментарий про перебалансировку.
|
|||
141
Salimbek
24.03.20
✎
14:06
|
+ что касаемо читаемости кода - код, оптимизированный под производительность, будет чуть менее читаемым, с этим надо просто смириться.
|
|||
142
sevod
24.03.20
✎
14:08
|
(141) если переменным дать человеческие название, компилятор тормозить начнет? :) Переменные надо по человечески называть.
|
|||
143
Кирпич
24.03.20
✎
14:08
|
(132) Напиши на 1с, что ты хочешь сделать и покажи. Второй день выясняем, что тебе нужно, блин. :))
|
|||
144
Salimbek
24.03.20
✎
14:16
|
(142) Там, в коде, введенные мной, переменные prev и nz. Я не думаю, что мне стоит их как-то еще переименовывать. Того, что есть - достаточно.
|
|||
145
yavasya
24.03.20
✎
14:18
|
(135) строки как 1С
|
|||
146
yavasya
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; } } |
|||
147
yavasya
24.03.20
✎
14:21
|
(141) не вижу связи
|
|||
148
ДНН
24.03.20
✎
14:27
|
удалил хоть, нет?
|
|||
149
Кирпич
24.03.20
✎
14:46
|
(148) Я думаю, еще дня три :)
|
|||
150
sevod
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
|
Наркоман наверное. Что со страной сделали....
|
|||
153
Конструктор1С
24.03.20
✎
15:59
|
(146) какая же это таблица значений? Если приближенно к 1с, это банальный массив структур получается
|
|||
154
MadHead
24.03.20
✎
16:18
|
(153) Я за sorted set.
|
|||
155
Доктор Манхэттен
24.03.20
✎
17:05
|
(105) >> В JS массивы - это скоере ассоциативный(индекс->значение) массив чем классический
C чего ты это взял? |
|||
156
Доктор Манхэттен
24.03.20
✎
17:14
|
(132) >> ты правильно понял задачу
Что??? Ты всю ветку писал что нужно удалить по значениям индексов, тут вдруг чел пишет что он думал что нужно удалить по значениям элементов, и ты пишешь что так и надо? Зачем же тогда столько времени всем голову морочил индексами? Это абсолютно разные задачи. Почему ты не можешь написать полное условие задачи, чтобы было проще тебе помочь? |
|||
157
fisher
24.03.20
✎
18:34
|
(146) Ну и покажи, как ты пробовал удалять по ссылке, что у тебя не получалось.
|
|||
158
Доктор Манхэттен
24.03.20
✎
19:30
|
Похоже ТС сам тролль, и пришел сюда вовсе не за помощью, раз даже не желает поделиться условием задачи.
|
|||
159
sevod
24.03.20
✎
20:49
|
(158)
Ну не, это же 1С форум. Тут же все телепаты :) Шутки, шутками, но у меня уже давно привычка не читать внимательно ТЗ, не слушать внимательно пользователей. Опыт подсказывает, что все будет не так как они говорят/пишут. И если вдруг, о ужас, ты с нормальным человеком общаешься, то попадаешь в неприятную ситуацию. |
|||
160
Asmody
24.03.20
✎
21:03
|
(158) Не, он не тролль, это он Битрикс на java пишет: Аналог Битрикс 24 на Java
|
|||
161
v77
24.03.20
✎
21:11
|
Понятно. Наркоман.
|
|||
162
cViper
24.03.20
✎
22:16
|
(160) Кстати, задача интересная, только во тя бы использовал другой язык программирования (фреймворк) для этого.
|
|||
163
Asmody
24.03.20
✎
22:18
|
(162) Пиши на Haskell.
|
|||
164
cViper
25.03.20
✎
00:26
|
(163) Мне вот в голову приходят только RoR и Django
|
|||
165
Доктор Манхэттен
25.03.20
✎
05:01
|
(164) Молодец, знаешь умные слова
|
|||
166
strange2007
25.03.20
✎
08:28
|
(0) >> В 1С для этого создается массив строк для удаления, и далее в метод удалить куда передается массив строк
Это неэффективный метод. Лучше коллекцию обходить с конца и по условиям удалять нужные строки. |
|||
167
Salimbek
25.03.20
✎
08:35
|
(166) Применительно к java - лучше делать как в (128)
|
|||
168
Кирпич
25.03.20
✎
09:51
|
(167) Вот так будет проще, понятнее и памяти меньше жрать на больших списках. И по скорости будет не хуже (128)
|
|||
169
Salimbek
25.03.20
✎
09:58
|
(168) Уверен? Понимаешь как работает remove на массиве Array?
|
|||
170
Кирпич
25.03.20
✎
10:00
|
(169) Уверен. Понимаю.
|
|||
171
fisher
25.03.20
✎
10:05
|
(168) Уже проходили. Самый эффективный вариант - использовать метод removeIf. Туда параметром можно передать прям предикат с условием удаления "строки" и он имеет оптимизацию для удаления пачки строк. Т.е. "схлопывает" массив не после удаления каждой строки (как делает remove), а один раз при удалении всех строк попадающих под условие удаления.
|
|||
172
Кирпич
25.03.20
✎
10:13
|
(171) верю. а в (128) точно пурга
|
|||
173
Кирпич
25.03.20
✎
10:16
|
(171) а как этот предикат нарисовать, имея список индексов, которые удалить надо? я в java только со вчерашнего дня :)
|
|||
174
Salimbek
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 |
|||
175
fisher
25.03.20
✎
10:26
|
(172) Почему пурга? Там как раз избегание "схлопывания" по remove за счет выделения дополнительной памяти. Немутабельная функция, все дела :) В теории должно быть быстрее. На практике утверждать не готов. Библиотечные функции могут использовать довольно эффективные оптимизации. Надо тестить.
|
|||
176
Salimbek
25.03.20
✎
10:26
|
(171) Код в (128) делает именно это.
|
|||
177
fisher
25.03.20
✎
10:29
|
(173) Так я готов поспорить, что ТС изначально не требуется удаление по списку индексов. Зуб даю (на самом деле нет), что он этот список индексов получил обходом коллекции и проверкой того самого условия.
|
|||
178
fisher
25.03.20
✎
10:32
|
(173) Для индексов тоже стопудово написать можно. Но "на гора" я его выдать не готов. Но было бы интересно сравнить производительность removeIf с (128)
|
|||
179
Salimbek
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}; |
|||
182
fisher
25.03.20
✎
11:06
|
(180) В тесте Salimbek удаляет 30 тысяч из 100 тысяч :)
|
|||
183
fisher
25.03.20
✎
11:06
|
А для нескольких элементов - да, накладные расходы могут перекрывать профит.
|
|||
184
Salimbek
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( т.е. опять же происходит ненужное создание доп. массива. Но уходить на уровени ниже для оптимизации производительности - лениво. |
|||
185
MadHead
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())); иначе - это преждевременная оптимизация. |
|||
186
MadHead
26.03.20
✎
06:52
|
(185) Работать на стримах будет медленнее, за то более модно )
|
|||
187
Salimbek
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, только извне доступа к нему нету). Но это уже кун-фу более высокого порядка ))) |
|||
188
Конструктор1С
26.03.20
✎
09:57
|
(179) сомнительная экономия. Ради выигрыша в сотые доли секунды, вместо использования библиотечного метода писать свой портяночный метод. К тому же, выиграв во времени выполнения, ты можешь проиграть в расходовании вычислительных ресурсов
|
|||
189
EVGA
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 |
|||
190
Salimbek
26.03.20
✎
11:10
|
(188) Вы о чем речь ведете?
1) Какой имеется "библиотечный метод", чтобы мы могли его использовать? Или надо написать код _используя_ библиотечные методы? 2) "Выигрыш в сотые доли секунды" - на каких объемах данных? Вот я попробовал удалить стандартным remove в массиве из 1 000 000 элементов 700 000 - так ответа и не дождался. Код работал более 10 секунд и вывалился по таймауту (а ставить себе java для этого баловства мне лень). (189) Наверное, потому, что надо именно удалить. Например, в Списке по условию могут быть и null-элементы (какая-нибудь выборка с БД с left_join). Или код завязан на количество строк, Или... да пофиг, что там еще... |
|||
191
fisher
26.03.20
✎
12:17
|
(179) Интересная инфа. Я думал, removeIf хуже себя поведет. А он вполне шустренько. Можно не заморачиваться в большинстве случаев.
|
|||
192
MadHead
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()); |
|||
193
cViper
27.03.20
✎
04:01
|
(187) Зачем изобретать свой велосипед. Проше взять готовый опенсорс и использовать его.
(190) Если нет ограничений по памяти, то быстрее будет скопировать оставшиеся 300_000 элементов в новый список вместо удаления 700_000 из старого. |
|||
194
cViper
27.03.20
✎
04:04
|
(190) Скиньте код сюда, интересно.
|
|||
195
Конструктор1С
27.03.20
✎
07:39
|
(190)
1. я имел ввиду, например, методы ArrayList public boolean removeAll(Collection c) public boolean removeIf(Predicate filter) 2. ну если много-много раз удалять через remove(int index) то конечно, можно и не дождаться. И вообще, если приходится таскать миллионы объектов в коллекциях, то это попахивает кривой архитектурой. Тут нужно думать не об написании своих методов с блэкджеком и шлюхами, взамен библиотечных, а о пересмотре архитектуры |
|||
196
Salimbek
27.03.20
✎
10:15
|
(195) И removeAll и removeIf работают со _значениями_ а надо было с _индексами_. Почему - не ко мне вопрос, я лишь баловался с алгоритмами.
(193) "быстрее будет скопировать оставшиеся 300_000 элементов в новый список" Дык, мой код как раз и делает именно это. И вообще, слишком много времени уже занимает это теоретическое исследование, без практического выхлопу ))) Поэтому далее тута общаться уже лень. Надеюсь, вы меня понимаете ))) |
|||
197
sevod
27.03.20
✎
10:32
|
Тут уже Вася с форума удалился, а вы все еще никак ArrayList не можете :)
|
|||
198
MadHead
27.03.20
✎
11:20
|
(197) Вероятнее всего автор сам себе выкрутил яйца заложенным подходом.
|
|||
199
fisher
27.03.20
✎
18:56
|
(196) Я вот тоже поудивлялся. То ли cViper критиковал твой код в (128) даже не удосужившись его прочитать, то ли сетовал как раз на то, что он заточен на большую долю удаляемых элементов.
|
|||
200
yavasya
27.03.20
✎
19:06
|
(197) я здесь дорогой) . это ты не можешь) не смог видимо стать программистом ООП, поэтому тебя бомбит от людей которые делают
|
|||
201
yavasya
27.03.20
✎
19:07
|
(199) не умеешь , не берись, тем более не оценивай. cViper было что то похожее на правду
|
|||
202
GANR
27.03.20
✎
20:39
|
||||
203
Конструктор1С
28.03.20
✎
05:04
|
(196) "надо было с _индексами_"
Очевидно, это какая-то тупая постановка задачи. Тем более, если стоит задача удалить дофига элементов из коллекции, то массив тут явно не подходит |
|||
204
sevod
28.03.20
✎
11:56
|
(202) а на эту ссылку всех пускает?
|
|||
205
sevod
28.03.20
✎
12:21
|
(202)
hasNext() не поможет, если надо по индексам удалять. Индексы смещаются при удалении и перестают соответствовать тем индексам которые были в первоначальном массиве. Отсортировать массив индексов от большего к меньшему и удалять по ним. То есть снизу вверх. Самый простой алгоритм. При таком удалении, смещение нижестоящих элементов, не изменяет индексы вышестоящих. Если конечно ему именно это нужно было. Но что бы дойти до такого супер сложного алгоритма, ему нужно свойства ArreyList прочитать, а не искать аналоги ArreyList в 1С. (200) Я даже в 1С ООП использую :) Так что бросай Java и ползи назад в 1С. Ну или хотя бы свойства ArreyList для Java прочитай. А то так и будешь вопросы по Java на 1С форуме задавать. |
|||
206
sevod
28.03.20
✎
12:30
|
(203) задача очень даже не тупая. Она для того что бы разобраться с особенностями ArreyList. У Васи например даже мысль возникла "Как сделать такую операцию в джава чтобы индексы не сбивались ? Или остается строка с ссылкой null ?". На практике скорее всего действительно не нужна.
Искать аналоги в 1С не стоит. В 1С разработчики платформы сделали намного проще, но цена за это "скорость" 1С. Кому очень хочется, может разобраться с массивами в Си и адресной арифметикой в Си. Но для 1С это все лишнее. |
|||
207
Сияющий в темноте
28.03.20
✎
14:59
|
нет
ну если отойти от программирования вообще и рассмотреть,скажем стопку из семи ящиков. если мы удаляем пятый ящик,то можно как-то сохранить нумерацию? очевидный ответ-нет,или мы вместо пятого ящика пихаем что-то его заменяющее или шестой ящик становится пятым. а представьте,что кто-то захочет вставить ящик между вторым и третьим? это,кстати,нашлядная модель поведенря индексов при изменении данных. |
|||
208
sevod
28.03.20
✎
15:40
|
(207) ты сейчас расписал часть работы ArreyList :) Наверное Вася и ждал такого поста :)
Если взять для сравнения Arrey, то это комод с выдвигающимися ящиками. Нельзя добавить или уменьшить количество ящиков комода. Только заменить на новый комод. А вот в ArreyList очень даже можно. Его для этого и создавали. Правда ArreyList это тоже комод, поскольку "по капотом" там Arrey, но вот реально, кому нужно, найдут нормальную статью. |
|||
209
GANR
28.03.20
✎
18:59
|
(205) Дак там по ссылке удалять можно же - никакие смещения не страшны
public static void main(String[] args) { ArrayList<Cat> cats = new ArrayList<>(); Cat thomas = new Cat("Томас"); Cat behemoth = new Cat("Бегемот"); Cat philipp = new Cat("Филипп Маркович"); Cat pushok = new Cat("Пушок"); cats.add(thomas); cats.add(behemoth); cats.add(philipp); cats.add(pushok); System.out.println(cats.toString()); cats.remove(philipp); System.out.println(cats.toString()); } Вывод: [Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Филипп Маркович'}, Cat{name='Пушок'}] [Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}] |
|||
210
sevod
28.03.20
✎
19:08
|
(209) А нам по "Ссылке" (наверное правильнее "по значению") или по индексу? :) Вася какие то намеки делает, но интригу продолжает сохранять :)
|
|||
211
Конструктор1С
28.03.20
✎
19:15
|
(206) а чё в 1с не так? 1сные коллекции во многом похожы на джавовые. При этом 1сное соответствие хитро оптимизировано, т.к. на нём завязаны многие платформенные механизмы. И пожалуй соответствие даже будет попроизводительнее джавового аналога в виде интерфейса Map
|
|||
212
Сияющий в темноте
28.03.20
✎
19:35
|
(208)
на самом деле,ArrayList работает так: при создании выделяется место,то есть создается комод на 4 ящика,все ящики заклеены,то есть не используются. добааляется первый элемент-распечатывается первый ящик, добавляется второй элемент-распечатывается второй ящик, также третий-в третий ящик теперь,если мы удаляем второй элемент,то мы должны выкинуть содержимое второго ящика потом содержимое третьего ящика переложить во второй и заклеить третий ящик. далее,если мы добавляем пятый элемент,то его засовывать некуда,система заказывает новый комод в два раза большего размера,перекладывает все существующие элементы и добавляет новый,а старый комод выбрасывается на помойку. и,быть может,система повторого использования выдаст этот комод еще кому-то,а если нет,то сборщик мусора окончательно уничтожит его. вот так. на самом деле,насколько я помню,первоначально выделяется 16 элементов,а потом не в два раза,а на одну треть больше,но суть от этого не меняется. |
|||
213
Сияющий в темноте
28.03.20
✎
19:52
|
и,на самом деле,если быть точным,то
в ящиках комода находятся дощечки,на которыз написан адрес(номер)обьекта,который саи размещается рядом с комодом,и мы не перемещаем дощечки,так как они в ящики встроены,а просто переписываем значение с одной дощечки на другую. когда нам меняют комод,то старый остается стоять на том же месте,где и был,новый появляется рядом и где-то на дощечке номер старого комода меняется на новый. опять же,место,где живут комоды и другие обьекты называется эдем-представим его ангаром. ангаров таких в системе два,когда один заполняется,и новый обьект не всунуть,то сборщик мусора начинает просматривать таблички в ппмяти программы и переносит уапомчнутые там обьекты в новый ангар,к каждого переносимого обьекта он просматривает все таблички,чтобы перенести упомянутые там обьекты и так до тех пор,пока переносить будет нечего. потом,все,что осталось в старом ангаре уничтожается,и старый ангар ждет следующей сборки мусора,где он будет принимающим. |
|||
214
sevod
28.03.20
✎
20:17
|
Вот так Вася, вот так ссын. Добился таки своего. ArreyList уже разжевали :) Расписывайте Arrey, без него ArreyList будет не точным.
По моим данным, на старте пустой ArreyList это 10 ячеек, далее увеличение идет на коэффициент 1,5. Но по сути это не принципиально. (211) проблема 1С в том, что нельзя по 1С учить java. Для изучения java, надо как ни странно читать документацию по java. Собственно и 1С по java учить тоже как то не очень умно. Но знание одного, может помочь с пониманием с другого. Но не всегда :) |
|||
215
Конструктор1С
29.03.20
✎
08:09
|
Накатал тест https://pastebin.com/WE71dQPw
Создаётся коллекция определенного размера. В этой коллекции ищется 10% значений. Затем из коллекции удаляются 10% значений Вывод: за поиск и удаление из ArrayList нужно бить по рукам. Эта коллекция не заточена под такие операции, и время вырастает пропорционально размеру массива. Но добавление значений в массив происходит очень быстро. Так что ArrayList нужно использовать как буфер Количество = 100000 TestArray: заполнение коллекции - 0.001 сек. TestArray: поиск в коллекции - 0.794 сек. TestArray: удаление из коллекции - 1.184 сек. TestMap: заполнение коллекции - 0.018 сек. TestMap: поиск в коллекции - 0.005 сек. TestMap: удаление из коллекции - 0.006 сек. Количество = 500000 TestArray: заполнение коллекции - 0.002 сек. TestArray: поиск в коллекции - 16.541 сек. TestArray: удаление из коллекции - 21.863 сек. TestMap: заполнение коллекции - 0.042 сек. TestMap: поиск в коллекции - 0.021 сек. TestMap: удаление из коллекции - 0.013 сек. Количество = 1000000 TestArray: заполнение коллекции - 0.002 сек. TestArray: поиск в коллекции - 65.444 сек. TestArray: удаление из коллекции - 108.472 сек. TestMap: заполнение коллекции - 0.073 сек. TestMap: поиск в коллекции - 0.026 сек. TestMap: удаление из коллекции - 0.025 сек. |
|||
216
Конструктор1С
29.03.20
✎
08:13
|
+ сам я не джавист, поэтому мог нарукожопить. Но в целом результат должен быть близок к правде
TestArray - выполняет заполнение, поиск и удаление в ArrayList (аналог 1сного массива) TestMap - выполняет заполнение, поиск и удаление в HashMap (аналог 1сного соответствия) |
|||
217
Конструктор1С
29.03.20
✎
08:25
|
(214) учить-то джаву по 1с однозначно не стоит. Но вот насчет "тормознутости" 1сных коллекций я не уверен. Разработчики платформы 1с тоже не в носу ковыряются, и некоторые моменты заточили как надо
|
|||
218
sevod
29.03.20
✎
10:49
|
(217) я не писал про тормознутость 1С коллекций. В яве есть Arrey и ArreyList. Второй значительно удобнее перового и медленнее. 1С-ый массив по функционалу аналогичен ArreyList и он разумеется медленнее Arrey.
|
|||
219
cViper
29.03.20
✎
13:59
|
(215) Глянул код. СОздавать коллекции лучше с помощью конструктора и с предполагаемым размером количества элементов, чтобы избежать постоянного расширения. Это очень сильно влияет на производительность.
Выводы которые вы написали, они очевидны и без вашего теста. (199) А я даже не вникал особо в код в (128) комментарии. Там говнокод написан. И мой комментарий из (193) относится исключительно к комментарию из (190). |
|||
220
yavasya
29.03.20
✎
20:06
|
(218) потому что в ArrayList можно добавить строки в отличие от Array
|
|||
221
v77
29.03.20
✎
20:33
|
(218) Да напиши ты хоть раз Array вместо Arrey. Ёлки моталки.
|
|||
222
sevod
29.03.20
✎
23:23
|
(221) Да как я это тебе напишу?! Тут IDE нет! Эта IDEA сама за меня все пишет. Знаю что лучше что нибудь по проще, но лень.
(220) Молодца, прогрессируешь. |
|||
223
v77
30.03.20
✎
09:23
|
(222) Ладно заливать. Не писал ты ничего и не читал. Потому и пишешь с ошибками.
|
|||
224
fisher
30.03.20
✎
09:55
|
(219) > А я даже не вникал особо в код в (128) комментарии
Да-да. Я заметил. На критику без "особого вникания" у вас времени полно. А на демонстрацию "как надо" примерами живого кода (что называется, вместо тысячи слов) времени не находится. Не царское это дело. Это ж, не дай бог, программировать придется. А там ведь и закритиковать могут. |
|||
225
cViper
31.03.20
✎
01:27
|
(224)
1) Есть такие принципы, как SOLID. Один из этих принципов рекомендует писать код отталкиваясь от интерфейса. То есть, в примере 128 надо принимать аргумент типа List<String> и возвращать также List<String>, вместо ArrayList<String>. Это урочень джуна. 2) Именование переменных как z и ii недопустимо. Оно ничего не говорит тому, кто будет этот код читать. Это тоже урочень джуна. 3) Зачем использовать разные структуры данных для значений и индексов? Либо человек не понимает как они работают, либо просто не знает как отсортировать List стандартными средствами jdk. Сам код, думаю, корректен. Но ковыряться в нем мне не интересно. Как можно решить задачу с индексами и с сохранением позиций я писал в одном из комментариев. Там настолько все просто, что не вижу смысло писать имлементацию. |
|||
226
Sserj
31.03.20
✎
03:42
|
(215) На самом деле не очень правильный тест применительно к топику.
В тесте удаление происходит через removeAll с коллекцией объектов. А это очень нехороший метод, посмотрев исходники ArrayList можно увидеть: final Object[] es = elementData; int r; // Optimize for initial run of survivors for (r = from;; r++) { if (r == end) return false; if (c.contains(es[r]) != complement) break; } Т.е. поиск ведется перебором массива ArrayList и поиском каждого элемента в переданной коллекции. В топике задача была на удаление по индексу, опять же посмотрев исходники ArrayList видим метод удаления по индексу: modCount++; final int newSize; if ((newSize = size - 1) > i) System.arraycopy(es, i + 1, es, i, newSize - i); es[size = newSize] = null; Тобишь фактически выполняется только System.arraycopy, которая в свою очередь является лишь оберткой над системной memcopy. Удаление по индексу в итоге будет не сильно отличаться по скорости от времени заполнения коллекции в тесте. |
|||
227
fisher
31.03.20
✎
09:10
|
(225) > настолько все просто, что не вижу смысло писать имлементацию
Ну вот опять. Чужой код настолько очевидно бездарен, что даже нет смысла в нем разбираться. А свой код настолько прост и самоочевидно идеален, что даже нет смысла его писать :) А вы возьмите и напишите. И другим наука будет на конкретном примере и вы без критики не останетесь. Авось тоже польза будет. |
|||
228
v77
31.03.20
✎
09:50
|
(225) "Там настолько все просто, что не вижу смысло писать имлементацию."
Это типа "моя фамилия слишком известна, чтобы я её называл" :)) |
|||
229
Sserj
31.03.20
✎
10:37
|
(225) "..Именование переменных как z и ii недопустимо. Оно ничего не говорит тому, кто будет этот код читать. Это тоже урочень джуна.."
хихи. В (226) выдержка из исходников jdk: int r; // Optimize for initial run of survivors for (r = from;; r++) ... Можешь смело утверждать что стандартную библиотеку явы писали джуны-лузеры :) |
|||
230
Конструктор1С
31.03.20
✎
15:23
|
(229) тем не менее, имена классов и объектов стандартных библиотек выбраны лаконично, интерфейсы хорошо задокументированы. Стандартную библиотеку дорабатывает только оракл, внуть библиотеки нырять не принято, разве что из интереса "что там под капотом". А вот твой код будут читать и дорабатывать другие программисты, которым односимвольные переменные будут не понятны. Поэтому всегда нужно выбирать хорошие описательные имена переменных/методов/классов
|
|||
231
Конструктор1С
31.03.20
✎
15:27
|
+кстати, имена переменных-счетчиков допускается делать короткими, вплоть до одного символа: i, j, k. Но это "так исторически сложилось". А вообще, чем больше область видимости у переменной, тем тщательнен должно быть выбрано её имя
|
|||
232
fisher
01.04.20
✎
09:28
|
(230) Строго говоря, описательные имена переменных больше касаются прикладного программирования. А в системном программировании и системных алгоритмах имена переменных часто не несут большого смысла достойного имен СКД во-первых (речь часто просто о тасовании безликих ячеек памяти), во-вторых - их количество обычно невелико в области видимости, в-третьих - они часто используются. Поэтому сплошь и рядом используют односимвольные/двухсимвольные имена переменных. Как раз для повышения читабельности, как бы на первый взгляд это парадоксально не звучало.
|
|||
233
Конструктор1С
02.04.20
✎
05:20
|
(232) тут скорее тоже "так исторически сложилось". Многие низкоуровневые ЯП имели ограничение на длину имен переменных
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |