Написание метода с ArrayList строк в качестве параметров

1

Я пытаюсь написать метод, который принимает 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)

Большое спасибо. Помощь приветствуется.

  • 0
    Пожалуйста, опубликуйте свою ошибку.
  • 0
    Прочитайте Javadoc List#add . Тогда ищите его перегруженный метод.
Показать ещё 6 комментариев
Теги:
arraylist
methods

6 ответов

8
Лучший ответ

Подумайте об этом фрагменте кода и притворитесь, что вы не получаете этого исключения:

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);

    }
}
  • 0
    «Компилятор Java также знает» - Нет, это не так. Concurrent Modification - исключение времени выполнения, а не ошибка компилятора, но остальная часть утверждения верна
  • 0
    @MadProgrammer Ооо, очень верно, мой плохой. Я исправлю это. Благодарю.
Показать ещё 6 комментариев
2

Эта...

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++;

Но что вы используете, зависит от вас...

  • 0
    не уверен, откуда взято отрицательное голосование, ваше - то же самое, что и голосование с повышенным голосом (может быть, после редактирования?). Если вы используете цикл for вместо стиля foreach, вам не нужен дополнительный indexof.
  • 0
    @JohnGardner Это правда. Вы должны любить мужество людей, которые отрицательно оценивают вопросы и ответы, не оставляя комментариев ... как люди предполагают учиться или имеют шанс улучшить качество поста: P
Показать ещё 8 комментариев
1

Проблема в том, что в вашем методе вы не изменяли каждую строку в 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 позволяет вам изменять список при повторении через него, а также позволяет вам вернуться назад в список.

  • 0
    Да, это то, что я думал, что ОП хотел бы сделать то же самое, но я думаю, что они хотят добавить "****" ПЕРЕД каждым соответствующим элементом, а не префикс его - может быть неправильно, но вот как я сейчас читаю это: P
  • 0
    Я только что обновил свой ответ на тот случай, если ОП хочет последнее.
1

Я бы использовал 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("****");
    }
}

Рабочий пример

  • 0
    Я думал, что это может сломаться, и, хотя мне нравится идея, он будет добавлять значения «после» последнего элемента, требуя начать возиться с previous , next ...: P
  • 0
    @MadProgrammer, точнее говоря, прежде всего означает итерацию в обратном порядке. Проверьте мой пример.
0

сделать временный 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);
    }
}
0

О, я помню эту прекрасную ошибку из старых добрых дней. Проблема заключается в том, что ваш 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 инициализатор.

  • 0
    Таким образом, я получил «Невозможно ссылаться на неконечные переменные слова внутри внутреннего класса, определенного в другом методе».

Ещё вопросы

Сообщество Overcoder
Наверх
Меню