Я пытаюсь написать метод, который принимает ArrayList of Strings в качестве параметра и помещает строку из четырех звездочек перед каждой строкой длиной 4.
Однако, в моем коде, я получаю ошибку в том, как я построил свой метод.
Вот мой класс длины метки
import java.util.ArrayList;
public class Marklength {
void marklength4(ArrayList <String> themarklength){
for(String n : themarklength){
if(n.length() ==4){
themarklength.add("****");
}
}
System.out.println(themarklength);
}
}
И вот мой основной класс:
import java.util.ArrayList;
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>();
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
Marklength ish = new Marklength();
ish.marklength4(words);
}
}
По существу в этом случае он должен работать, поэтому он добавляет arraylist со строкой "****"
помещенной перед каждым предыдущим элементом списка массивов, потому что длина строк равна 4.
КСТАТИ
Это состоит из добавления другого элемента
Я не знаю, где я ошибся. Возможно, в моей петле?
Я получил следующую ошибку:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at Marklength.marklength4(Marklength.java:7)
at MarklengthTestDrive.main(MarklengthTestDrive.java:18)
Большое спасибо. Помощь приветствуется.
Подумайте об этом фрагменте кода и притворитесь, что вы не получаете этого исключения:
import java.util.ArrayList;
public class Marklength {
void marklength4(ArrayList <String> themarklength){
for(String n : themarklength){
if(n.length() ==4){
themarklength.add("****");
}
}
System.out.println(themarklength);
}
}
Итак, что произойдет, если ваш список просто содержит item
.
Вы попадаете в строку if(n.length() ==4){
, это правда, потому что вы смотрите на элемент, поэтому вы идете выполнить его блок.
Затем вы нажмете на строку themarklength.add("****");
, Теперь у вашего списка есть элемент ****
в конце его.
Цикл продолжается, и вы получаете следующий элемент в списке, который, оказывается, тот, который вы только что добавили, ****
.
Следующая строка, на которую вы if(n.length() ==4){
- if(n.length() ==4){
. Это верно, поэтому вы выполняете свой блок. Вы переходите к строке themarklength.add("****");
, и добавьте ****
в конец списка.
Мы видим здесь плохую картину? Да, да, мы делаем.
Среда выполнения Java также знает, что это плохо, поэтому она предотвращает нечто, называемое Concurrent Modification. В вашем случае это означает, что вы не можете изменить список во время итерации по нему, что и делает это для цикла.
Мое лучшее предположение о том, что вы пытаетесь сделать, это примерно так:
import java.util.ArrayList;
public class Marklength {
ArrayList<String> marklength4(ArrayList <String> themarklength){
ArrayList<String> markedStrings = new ArrayList<String>(themarklength.size());
for(String n : themarklength){
if(n.length() ==4){
markedStrings.add("****");
}
markedStrings.add(n);
}
System.out.println(themarklength);
return markedStrings;
}
}
А потом:
import java.util.ArrayList;
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>();
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
Marklength ish = new Marklength();
words = ish.marklength4(words);
}
}
Concurrent Modification
- исключение времени выполнения, а не ошибка компилятора, но остальная часть утверждения верна
Эта...
if(n.length() ==4){
themarklength.add("****");
}
Просто пытается добавить "****"
в конец списка. Это терпит неудачу, потому что Iterator
используемый циклом for-each
, не позволит изменениям в базовом List
когда он был повторен.
Вы можете сначала создать копию List
...
List<String> values = new ArrayList<String>(themarklength);
Или преобразовать его в массив String
String[] values = themarklength.toArray(new String[themarklength.size()]);
И использует их, как вы итерации точки...
for (String value : values) {
Затем вам нужно будет вставить новый элемент в ArrayList
в определенную точку. Для этого вам нужно знать исходный индекс значения, с которым вы работаете...
if (value.length() == 4) {
int index = themarklength.indexOf(value);
А затем добавьте новое значение в нужное место...
themarklength.add(index, "****");
Это добавит "****"
в index
точку, нажав все остальные записи вниз
обновленный
Как было правильно указано на мне, использование themarklength.indexOf(value)
не будет учитывать случай использования, когда список themarklength
содержит два элемента одного и того же значения, которые возвращают неверный индекс.
Я также не фокусировался на производительности в качестве основного требования для обеспечения возможного решения.
Обновление...
Как указывалось JohnGarnder и AnthonyAccioly, вы можете использовать for-loop
вместо for-each
который позволит вам обойтись без themarklength.indexOf(value)
Это устранит риск дублирования значений, испортивших местоположение индекса и улучшающих общую производительность, поскольку вам не нужно создавать второй итератор...
// This assumes you're using the ArrayList as the copy...
for (int index = 0; index < themarklength.size(); index++) {
String value = themarklength.get(index);
if (value.length() == 4) {
themarklength.add(index, "****");
index++;
Но что вы используете, зависит от вас...
Проблема в том, что в вашем методе вы не изменяли каждую строку в arraylist, а добавляли только 4 звезды к списку. Итак, правильный способ сделать это - вам нужно изменить каждый элемент массива и заменить старую строку на новую:
void marklength4(ArrayList<String> themarklength){
int index = 0;
for(String n : themarklength){
if(n.length() ==4){
n = "****" + n;
}
themarklength.set(index++, n);
}
System.out.println(themarklength);
}
Если это не то, что вам нужно, но вы хотите добавить новую строку "**" перед каждым элементом в arraylist, вы можете использовать метод listIterator
в ArrayList
чтобы добавить новый дополнительный элемент до строки EACH, если длина равна 4.
ListIterator<String> it = themarklength.listIterator();
while(it.hasNext()) {
String name = it.next();
if(name.length() == 4) {
it.previous();
it.add("****");
it.next();
}
}
Разница заключается в следующем: ListIterator позволяет вам изменять список при повторении через него, а также позволяет вам вернуться назад в список.
"****"
ПЕРЕД каждым соответствующим элементом, а не префикс его - может быть неправильно, но вот как я сейчас читаю это: P
Я бы использовал ListIterator вместо a для каждого, listiterator.add
скорее всего сделает именно то, что вы хотите.
public void marklength4(List<String> themarklength){
final ListIterator<String> lit =
themarklength.listIterator(themarklength.size());
boolean shouldInsert = false;
while(lit.hasPrevious()) {
if (shouldInsert) {
lit.add("****");
lit.previous();
shouldInsert = false;
}
final String n = lit.previous();
shouldInsert = (n.length() == 4);
}
if (shouldInsert) {
lit.add("****");
}
}
previous
, next
...: P
сделать временный arraylist, изменить этот список и скопировать его содержимое в конце в исходный список
import java.util.ArrayList;
public class MarkLength {
void marklength4(ArrayList <String> themarklength){
ArrayList<String> temp = new ArrayList<String>();
for(String n : themarklength){
if(n.length() ==4){
temp.add(n);
temp.add("****");
}
}
themarklength.clear();
themarklength.addAll(temp);
System.out.println(themarklength);
}
}
О, я помню эту прекрасную ошибку из старых добрых дней. Проблема заключается в том, что ваш ArrayList
не полностью заполнен к тому моменту, когда элемент массива должен быть доступен. Подумайте об этом, вы создаете объект, а затем сразу начинаете его зацикливать. Следовательно, объект должен заполнять себя значениями, когда цикл будет запущен.
Простой способ решить это - предварительно заполнить свой ArrayList.
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>() {{
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
}};
}
}
Скажите мне, исправляет ли это это. Вы также можете использовать static
инициализатор.
List#add
. Тогда ищите его перегруженный метод.