2014-03-28 64 views
1

我想寫這需要字符串的ArrayList作爲參數的方法,並且放置四個星號的字符串長度的每個字符串的前4寫作與字符串的ArrayList的方法作爲參數

然而,在我的代碼,我在我建立我的方法的方式得到一個錯誤。

這裏是我的標記長度類

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

這包括添加其他元素

的我不知道我哪裏錯了。可能在我的循環?

我得到了以下錯誤:

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

請發表您的錯誤也是如此。 – Makri

+0

閱讀'List#add'的javadoc。然後查找它的重載方法。 –

+1

您正試圖修改爲該foreach循環創建的臨時變量:http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work,http:// docs。 oracle.com/javase/1.5.0/docs/guide/language/foreach.html – MirroredFate

回答

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

    } 
} 
+0

*「Java編譯器也知道」 * - 不,它不需要'併發Modification'是一個運行時異常,而不是一個編譯器錯誤,但聲明的其餘部分是真實的 – MadProgrammer

+0

@MadProgrammer哦,很真實,是我不好。我會解決這個問題。謝謝。 – MirroredFate

+0

好的,爲了賺取+1,你會建議做什麼修復? ;) – MadProgrammer

2

這...

if(n.length() ==4){ 
    themarklength.add("****"); 
} 

只是想添加"****"到列表的末尾。失敗的原因是由for-each循環使用的Iterator不會允許同時它已經迭代的變化而出現的潛在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

不確定downvote來自哪裏,如果你使用for循環而不是foreach樣式,那麼你和upvoted的一樣(可能是後期編輯?),你不需要額外的indexof。 –

+0

@JohnGardner確實如此。你必須愛那些沒有留下評論就冷靜回答問題和答案的人的勇氣......如何人想學習或具有完善的後期質量的機會:P – MadProgrammer

+0

@JohnGardner我肯定不是爲了選票,因爲我幫助了導致問題提供了可能的答案;) – MadProgrammer

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

所以我就 「不能指非最終變量的話中定義的內部類中一種不同的方法。「 –

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

如果這不是你想要的,但你要添加一個新的字符串「* *」之前的數組列表的每個元素,則可以使用listIterator方法在ArrayList每個字符串之前添加新附加元素,如果長度爲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

是的,這就是我認爲OP想要做的,但我相信他們希望在每個匹配元素之前添加「****」,而不是前綴 - 可能是錯誤的,但這就是我現在閱讀它的原因:P – MadProgrammer

+0

我剛剛更新了我的回答,以防OP需要後者。 – tonga

1

我會用一個ListIterator,而不是每個,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("****"); 
    } 
} 

Working example

+0

我想這可能打破,而我喜歡這個主意,它會在最後一個元素「之後」添加值,需要開始擺弄'previous','next' ...:P – MadProgrammer

+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); 
    } 
} 
相關問題