2017-12-22 26 views
1

이것은 예상했던 것보다 어렵습니다. 나는 정렬 된 ArrayList of Strings (단어)를 가지고 있고, 나의 임무는 반복을 제거하고 각 단어의 목록을 출력하고 그 다음에 단어의 반복 번호를 출력하는 것이다. 그것이 내가 예상했던 것보다 더 복잡하다고 말하면 충분합니다. 다른 것을 시도한 후에, 나는 HashMap을 사용하여 단어 (키), 값 (반복)을 저장하기로 결정했다.ArrayList에서 중복 요소 및 개수 반복 제거

이것은 코드입니다. 사전은 정렬 된 ArrayList이고 반복은 HashMap입니다. 내가 이해하지 못하는 몇 가지 이유 (I 초보자 해요)에 대한

public void countElements() 
    { 
    String word=dictionary.get(0); 
      int wordCount=1; 
      int count=dictionary.size(); 
      for (int i=0;i<count;i++) 
      { 
       word=dictionary.get(i); 

       for (int j=i+1; j<count;j++) 
       { 


        if(word.equals(dictionary.get(j))) 
        { 

         wordCount=wordCount+1; 
         repetitions.put(word, wordCount);       
         dictionary.remove(j--);        
         count--; 

        } 


       } 
      } 

, 나는 (j--) 방법 (1)에 의한 변수 J으로 감의 dictionary.remove를 호출 후 난을해야하더라도 + 1. 내가 뭘 놓치고 있니? 이 작업을 올바르게 수행하는 방법에 대한 아이디어는 인정 될 것입니다. iterator를 사용하는 것이 가장 좋을지 모르지만, 그것은 훨씬 더 혼란스럽게 될 수 있습니다. 많은 감사.

+0

반복자를 사용하는 것이 좋지 않습니다. –

+1

당신은 그것을 overthinking. 목록을 정렬 할 필요조차 없습니다. 각 단어에 대해 이미지도에 있는지 확인합니다. true이면 맵의 값을 증가시키고, 그렇지 않으면 값을 1로 맵에 추가합니다. 스트림을 사용하면 1 행의 코드에서이를 수행 할 수 있습니다. –

답변

0

이 코드는 귀하의 목적에 부합 할 것입니다. 이제 사전에는 고유 한 단어가 포함될 것이고 hashmap에는 각 단어의 빈도가 포함될 것입니다. 우리 기 (Collectors.groupingBy 사용) 여기서

final Map<String, Long> countMap = dictionary.stream().collect(
      Collectors.groupingBy(word -> word, LinkedHashMap::new, Collectors.counting())); 
    System.out.println("Counts follow"); 
    System.out.println(countMap); 
    System.out.println("Duplicate-free list follows"); 
    System.out.println(countMap.keySet()); 

얻어진 맵의 키로서, 각 요소 (즉, 각각의 워드)을 이용하여리스트의 요소 및 계수 : 스트림을 사용

public class newq { 

    public static void main(String[] args) 
    { 
     ArrayList<String> dictionary=new ArrayList<String>(); 
     dictionary.add("hello"); 
     dictionary.add("hello"); 
     dictionary.add("asd"); 
     dictionary.add("qwet"); 
     dictionary.add("qwet"); 
     HashMap<String,Integer> hs=new HashMap<String,Integer>(); 
     int i=0; 
     while(i<dictionary.size()) 
     { 
      String word=dictionary.get(i); 
      if(hs.containsKey(word)) // check if word repeated 
      { 
       hs.put(word, hs.get(word)+1); //if repeated increase the count 
       dictionary.remove(i); // remove the word 

      } 
      else 
      { 
       hs.put(word, 1); //not repeated 
       i++; 
      } 

     } 
     Iterator it = hs.entrySet().iterator(); 
     while(it.hasNext()) 
     { 
      HashMap.Entry pair = (HashMap.Entry)it.next(); 
      System.out.println(pair.getKey() + " = " + pair.getValue()); 
      it.remove(); 
     } 
     for(String word: dictionary) 
     { 
      System.out.println(word); 
     } 
    } 
} 
+1

오 마이. 원시 형식을 사용하지 마십시오. 반복기에 대해 알고 있기 때문에 첫 번째 루프에 하나를 사용하는 것이 어떻습니까? 그것은 훨씬 더 안전하고 분명합니다. Map.merge()를 사용하는 것이 더 간단합니다. –

+0

응답 해 주신 모든 분들께 감사드립니다. 너는 매우 도움이되었다. 그리고 네, JB Nizet이 말했듯이 저는 그것을 조금 지나치게 생각했습니다. (너무 많은 시간을 보냈습니다.) 아직 이해할 수없는 마지막 것이 하나 있습니다. 왜 내 dictionary.remove (j--) 메서드 호출 후 j 값이 1 씩 감소합니다. j 변수에 새 값을 할당하지 않았으므로 감소하지 않아야합니까? 나는 디버거와 print 문을 사용하여 검사했다. 나는 확실히 뭔가를 놓친다. – Apollonius

1

버전 이 단어는 (Collectors.counting()을 사용하여) 발생합니다.

외부 수집기 (groupingBy)는 counting 수집기를 단일 단어의 모든 발생을 수집 (여기에서 계산)하는 다운 스트림 수집기로 사용합니다.

LinkedHashMap은 초기 목록에있는 단어와 동일한 순서를 유지하기 위해 키 - 값 쌍이 추가 된 순서를 유지하기 때문에 여기에서 LinkedHashMap을 사용하고 있습니다.

그리고 한 가지 더 : countMap.keySet()List이 아닙니다. 결국 List을 얻으려면 new ArrayList(countMap.keySet())입니다.

+0

그러나 목록에서 중복을 제거하지는 않습니다. –

+0

죄송합니다. 잊어 버렸습니다. 답변을 조정했습니다. –

0

'j'를 감소시키지 않으려면 j-1을 사용해야합니다. j -, - j, j ++ 또는 ++ j를 사용하면 변수 값이 변경됩니다.

This link에는 post-en pre-incrementing에 대한 좋은 설명과 간단한 예가 있습니다.

+0

많은, 많은 감사드립니다. 이러한 차이는 아주 미묘하고 찾기가 쉽지 않습니다. – Apollonius