2009-03-02 3 views
0

내 문제는 실제로 질문보다 더 미묘한 차이가 있지만 헤더를 간략하게 유지하려고합니다.HashMap에서 추출한 값의 순서 목록을 어떻게 만들 수 있습니까?

나는 HashMap<String, File>의 값이 File입니다. 키는 File 인스턴스의 일부인 String name 필드입니다. HashMap의 값을 반복하여 단일 String으로 반환해야합니다. 이 작업을 수행

private String getFiles() 
{ 
    Collection<File> fileCollection = files.values(); 
    StringBuilder allFilesString = new StringBuilder(); 

    for(File file : fileCollection) { 
     allFilesString.append(file.toString()); 
    } 
    return allFilesString.toString(); 
} 

하지만, 이상적으로는 별도의 File 값은 File 클래스의 필드가 int fileID의 순서에 StringBuilder에 추가 할 :

내가 현재 가지고있는 것입니다 .

희망을 충분히 밝혔습니다.

+0

성능 비용을 감당할 수 있으면 SortedMap (TreeMap 등)을 사용하려고합니다. – Powerlord

답변

6

뭔가 작동합니다 :

List<File> fileCollection = new ArrayList<File>(files.values()); 

Collections.sort(fileCollection, 
       new Comparator<File>() 
       { 
        public int compare(File fileA, File fileB) 
        { 
         final int retVal; 

         if(fileA.fileID > fileB.fileID) 
         { 
          retVal = 1; 
         } 
         else if(fileA.fileID < fileB.fileID) 
         { 
          retVal = -1; 
         } 
         else 
         { 
          retVal = 0; 
         } 

         return (retVal);       
        } 
       }); 
+0

정수를 오버 플로우 시키십시오! –

+0

감사합니다. 제안한 변경 사항을 구현했습니다. 아래를 참조하십시오. – darrengorman

+0

return fileA.fileID - fileB.fileID; – akuhn

4

불행히도 HashMap에서 데이터를 인식 할 수있는 순서로 가져올 방법이 없습니다. 모든 값을 FileSet을 사용하는 Comparator를 사용하여 TreeSet에 저장하거나 ArrayList에 저장하고 Collections.sort를 사용하여 원하는대로 비교하는 Comparator로 다시 정렬해야합니다.

중복이있는 경우 TreeSet 메서드가 작동하지 않으며 Set에 사물을 추가하거나 제거하지 않으므로 잔인 할 수 있습니다. Collections.sort 메서드는 전체 HashSet을 가져 와서 결과를 정렬 한 다음 결과를 생성하자마자 정렬 된 컬렉션을 던지려고 할 때 이와 같은 인스턴스에 적합한 솔루션입니다.

+0

TreeSet의 요소는 값이 아닌 키에 따라 정렬됩니다. – pgras

+0

TreeSet에는 키가 없습니다. 당신은 TreeMap을 생각하고 있습니다. –

0

배열로 수집하여 정렬 한 다음 정렬하여 연결하십시오.

- MarkusQ

0

당신은 ArrayList에에 값() 컬렉션을 추가하고 반복하기 전에 사용자 정의 비교기 인스턴스은, Collections.sort()를 사용하여 정렬해야합니다.

둘째, 콜렉션 크기에 따라 StringBuffer를 초기화하는 것은 의미가 없습니다. 콜렉션 요소 당 1 문자 이상을 추가 할 것이기 때문입니다.

0

이 컬렉션의 세트에 추가되기 전에 나는 수십 번의 LinkedHashMap 만든 다음

당신이 찾고있는 방법이다.

아마도 TreeHashMap 컬렉션을 만들면됩니다.

두 번째 컬렉션을 만들고 두 가지 컬렉션을 모두 추가하는 것은 실제로는 큰 타격이 아니며 둘 다 추가 할 때 약간의 시간이 소요됩니다.

새로운 컬렉션으로 사용하면 코드를 깨끗하고 깔끔하게 유지하는 데 도움이됩니다. 컬렉션 클래스는 단지 몇 줄이어야하며 기존 해시 맵을 대체해야합니다.

언제나 컬렉션을 포장하는 습관을 갖고 있다면,이 재료는 효과가 있습니다. 생각조차 할 수 없습니다.

0
StringBuffer allFilesString = new StringBuffer(fileCollection.size()); 

모든 file.toString()이 평균 한 문자가 아닌 이상 StringBuffer를 너무 작게 설정했을 수 있습니다. (맞지 않으면 코드를 설정하지 않고 코드를 더 간단하게 만들 수 있습니다.) 크기를 여러 배로 만들면 더 나은 결과를 얻을 수 있습니다. 또한 StringBuffer는 동기화되지만 StringBuilder는 여기에 없으며 더 효율적입니다.

+0

Thanks Peter, StringBuilder를 StringBuilder로 대체하고 생성자에서 매개 변수를 제거했습니다. – darrengorman

1

오케이, 이것이 내가 생각해 낸 것입니다. 문제를 해결하는 것으로 보입니다. File 객체로 멋지게 정렬 된 File 객체로 String을 반환합니다.

public String getFiles() 
{ 
    List<File> fileList = new ArrayList<File>(files.values()); 

    Collections.sort(fileList, new Comparator<File>() 
           { 
            public int compare(File fileA, File fileB) 
            { 
             if(fileA.getFileId() > fileB.getFileId()) 
             { 
              return 1; 
             } 
             else if(fileA.getFileId() < fileB.getFileId()) 
             { 
              return -1; 
             } 
             return 0; 
            } 
           }); 

    StringBuilder allFilesString = new StringBuilder(); 

    for(File file : fileList) { 
     allFilesString.append(file.toString()); 
    } 
    return allFilesString.toString(); 
} 

내가 전에 비교기를 사용한 적이 (상대적으로 자바에 새로운), 그래서 잘못 아무것도 구현 한 경우 어떤 의견을 보내 주셔서 감사합니다.

0

불필요한 if를 제거하십시오.

List<File> fileCollection = new ArrayList<File>(files.values()); 
Collections.sort(fileCollection, 
      new Comparator<File>() { 
       public int compare(File a, File b) { 
        return (a.fileID - b.fileID); 
       } 
      }); 
관련 문제