У меня есть этот код:
public static String SelectRandomFromTemplate(String template,int count) {
String[] split = template.split("|");
List<String> list=Arrays.asList(split);
Random r = new Random();
while( list.size() > count ) {
list.remove(r.nextInt(list.size()));
}
return StringUtils.join(list, ", ");
}
Я получаю это:
06-03 15:05:29.614: ERROR/AndroidRuntime(7737): java.lang.UnsupportedOperationException
06-03 15:05:29.614: ERROR/AndroidRuntime(7737): at java.util.AbstractList.remove(AbstractList.java:645)
Как это будет правильно? Java.15
Ответы:
Довольно много проблем с вашим кодом:
При
Arrays.asList
возврате списка фиксированного размераИз API:
Вы не можете
add
к этому; ты не можешьremove
от этого. Вы не можете структурно изменитьList
.Fix
Создайте
LinkedList
, который поддерживает быстрееremove
.О
split
принятии регулярных выраженийИз API:
|
является метасимволом регулярных выражений; если вы хотите разделить литерал|
, вы должны экранировать его\|
, как строковый литерал Java"\\|"
.Fix:
По лучшему алгоритму
Вместо того, чтобы вызывать по
remove
одному со случайными индексами, лучше генерировать достаточно случайных чисел в диапазоне, а затем обходитьList
один раз с помощью alistIterator()
, вызываяremove()
соответствующие индексы. Есть вопросы о потоке стека о том, как генерировать случайные, но разные числа в заданном диапазоне.С этим ваш алгоритм будет
O(N)
.источник
Random
каждый раз. Сделайте этоstatic
поле и посейте его только один раз.Это сожгло меня много раз.
Arrays.asList
создает неизменяемый список. Из Javadoc: Возвращает список фиксированного размера, поддерживаемый указанным массивом.Создайте новый список с тем же содержанием:
Это создаст немного лишнего мусора, но вы сможете изменить его.
источник
Возможно, потому что вы работаете с неизменяемой оболочкой .
Измените эту строку:
к этой строке:
источник
unmodifiable
иimmutable
.unmodifiable
означает именно «изменяемый, но не конструктивно».unmodifiableList
обертку и попробоватьset
; это бросаетUnsupportedOperationException
. Я совершенно уверен, что наCollections.unmodifiable*
самом деле означает полную неизменность, а не только структурную.Я думаю, что замена:
с
решает проблему.
источник
Возвращаемый список
Arrays.asList()
может быть неизменным. Не могли бы вы попробоватьисточник
Просто прочитайте JavaDoc для метода asList:
Это из Java 6, но похоже, что это то же самое для Android Java.
РЕДАКТИРОВАТЬ
Тип результирующего списка
Arrays.ArrayList
- это закрытый класс внутри Arrays.class. На практике это не что иное, как представление списка в массиве, с которым вы прошлиArrays.asList
. С последствием: если вы измените массив, список тоже изменится. А поскольку размер массива не может быть изменен, операция удаления и добавления не должна поддерживаться.источник
Arrays.asList () возвращает список, который не допускает операций, влияющих на его размер (обратите внимание, что это не то же самое, что «неизменяемый»).
Вы могли бы сделать,
new ArrayList<String>(Arrays.asList(split));
чтобы создать реальную копию, но, посмотрев, что вы пытаетесь сделать, вот дополнительное предложение (у вас естьO(n^2)
алгоритм прямо под этим).Вы хотите удалить
list.size() - count
(давайте назовем этоk
) случайные элементы из списка. Просто выберите как можно больше случайных элементов и поменяйте их местами в концеk
списка, затем удалите весь этот диапазон (например, с помощью subList () и clear () для этого). Это превратит его в простой и среднийO(n)
алгоритм (O(k)
точнее).Обновление : как отмечено ниже, этот алгоритм имеет смысл только в том случае, если элементы неупорядочены, например, если List представляет Bag. Если, с другой стороны, список имеет значимый порядок, этот алгоритм не будет его сохранять (вместо этого будет алгоритм полигенасыщенных смазок).
Обновление 2 : Итак, ретроспективно, лучший алгоритм (линейный, поддерживающий порядок, но с O (n) случайными числами) будет выглядеть примерно так:
источник
ArrayList
. Гораздо проще, чем мое предложение. Я думаю, что это приведет к переупорядочению элементов.У меня есть другое решение этой проблемы:
работать на
newList
;)источник
Это исключение UnsupportedOperationException возникает, когда вы пытаетесь выполнить какую-либо операцию с коллекцией, где это не разрешено, и в вашем случае, когда вы вызываете
Arrays.asList
ее, она не возвращает ajava.util.ArrayList
. Возвращает список,java.util.Arrays$ArrayList
который является неизменным. Вы не можете добавить к нему, и вы не можете удалить из него.источник
Да, включен
Arrays.asList
, возвращая список фиксированного размера.Помимо использования связанного списка, просто используйте
addAll
список методов.Пример:
источник
замещать
в
или
или
или (лучше для удаления элементов)
источник
Arraylist narraylist = Arrays.asList (); // Возвращает неизменяемый arraylist Чтобы сделать его изменяемым, было бы следующее: Arraylist narraylist = new ArrayList (Arrays.asList ());
источник
Ниже приведен фрагмент кода из массивов
так что происходит, когда метод asList вызывается, он возвращает список своих собственных версий статического класса, который не переопределяет функцию add из AbstractList для хранения элемента в массиве. Поэтому по умолчанию метод add в абстрактном списке генерирует исключение.
Так что это не обычный список массивов.
источник
Вы не можете удалить и не можете добавить в список массивов фиксированного размера.
Но вы можете создать свой подсписок из этого списка.
list = list.subList(0, list.size() - (list.size() - count));
* Другой способ
это создаст ArrayList, который не имеет фиксированный размер, как Arrays.asList
источник
Arrays.asList()
использует массив фиксированного размера внутри.Вы не можете динамически добавлять или удалять из этого
Arrays.asList()
Использовать этот
В
narraylist
вы можете легко добавлять или удалять предметы.источник
Создание нового списка и заполнение допустимых значений в новом списке работало для меня.
Ошибка при создании кода -
После исправления -
источник