我正在尝试编写一个方法,该方法将String的StringList作为参数,并在每个长度为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.
BTW
这包括添加其他元素
我不确定我哪里出错了。可能在我的for循环中?
我收到以下错误:
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 :(得分: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){
。这是真的,所以你执行它的块。
您转到第themarklength.add("****");
行,然后将****
添加到列表的末尾。
我们在这看到一个糟糕的模式吗?是的,是的,我们这样做。
Java运行时环境也知道这很糟糕,这就是为什么阻止称为并发修改的东西。在您的情况下,这意味着您在迭代时不能修改列表,这就是for循环所做的。
我最好猜测你要做的是这样的事情:
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);
}
}
答案 1 :(得分: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++;
但你使用的取决于你...
答案 2 :(得分:1)
问题在于,在您的方法中,您没有修改arraylist中的每个字符串,而只是在列表中添加了4个星。所以正确的方法是,你需要修改arraylist的每个元素,并用新的字符串替换旧的字符串:
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
方法如果长度为4,则在EACH字符串之前添加新的附加元素。
ListIterator<String> it = themarklength.listIterator();
while(it.hasNext()) {
String name = it.next();
if(name.length() == 4) {
it.previous();
it.add("****");
it.next();
}
}
区别在于:ListIterator允许您在迭代时修改列表,并允许您在列表中向后移动。
答案 3 :(得分:1)
我会使用ListIterator代替每个listiterator.add
,Working example可能完全按照您的意愿行事。
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("****");
}
}
{{3}}
答案 4 :(得分: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
初始化程序。
答案 5 :(得分: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);
}
}