2013-11-08 2 views
1

Я не очень хорошо знаком с Java, и я немного не уверен, как перевести это из C# в java.Как вы можете сгенерировать список N отсортированных ключей хэш-карты, сортируя по значению?

Dictionary<string, int> myDictionary = GetDictionary(); 
int N = 10; 

myDictionary 
     .OrderByDescending(dictionaryEntry => dictionaryEntry.Value) 
     .Take(N) 
     .Select(dictionaryEntry => dictionaryEntry.Key) 
     .ToList(); 

Теперь я знаю, словарь сам разве сортируется, его просто новый IEnumberable, и это нормально.

Спасибо!

ответ

1

Я не C# парня, я никогда не работал с ним, но если я должен сделать предположение, кажется, как вы сортировка карты по ее значениям в порядке убывания, извлекая 10 первых элементов , затем преобразование ключей из этих 10 элементов в список.

Если значения, как известно, отличаются друг от друга, то это просто тривиально - вы просто конвертируете в SortedMap с замененными ключами и значениями. Поэтому я предполагаю, что значения не различаются, т. Е. Один и тот же номер может появляться несколько раз.

В этом случае это не так, как тривиально, и определенно не так просто, как в примере на C#. Моя первая мысль заключалась в создании сортированного набора с помощью специального компаратора, где каждый элемент в наборе является Map.Entry с вашей карты, где ключи и значения обмениваются.

Это фактически потребует довольно много кода на Java. Heres одна попытка:

// Create a SortedSet of the reversed entry set, with a custom comparator for sorting 
SortedSet<Map.Entry<Integer, String>> sortedSet = new TreeSet<Map.Entry<Integer, String>>(
     new Comparator<Map.Entry<Integer, String>>() { 
    public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) { 
     // sort by key, then by value --> in descending order 
     int keyCompareResult = -o1.getKey().compareTo(o2.getKey()); // negate --> descending 
     int valueCompareResult = o1.getValue().compareTo(o2.getValue()); 
     return keyCompareResult == 0 ? valueCompareResult : -keyCompareResult; 
    } 
}); 

// Add all entries of the map to the sorted set 
for (Map.Entry<String, Integer> entry : map.entrySet()) { 
    Map.Entry<Integer, String> reversedEntry = new AbstractMap.SimpleEntry<Integer, String>(entry.getValue(), entry.getKey()); 
    sortedSet.add(reversedEntry); 
} 

// Convert the 10 first elements to the resulting list 
int N = 10; 
List<String> result = new ArrayList<String>(N); 
Iterator<Map.Entry<Integer,String>> iterator = sortedSet.iterator(); 
while (iterator.hasNext() && result.size() < N) { 
    Map.Entry<Integer, String> entry = iterator.next(); 
    result.add(entry.getValue()); 
} 
+0

Спасибо! После поиска немного я закончил делать что-то подобное, но я не знал о классе SortedSet, поэтому я сделал ArrayList реализовал небольшой класс для компаратора, а затем использовал Collections.sort (myArrayList, Collections.reverseOrder (новый MapEntryComparator())); Для выбора элементов Top N, это почти то же самое, что и для. Я добавлю свой ответ для полноты, но он почти такой же, как у вас, поэтому я дам вам ответ :) –

+0

Хотя, если кто-нибудь знает о более LINQ-y/функциональном способе сделать это, добавьте ответ! –

-1

Начнем с произвольной HashMap, которую вы приобрели, как-то определённой HashMap<String, Integer> map.

Мы хотим отсортировать значения, а затем получить первые N значений.

int N = 10; 

List<Integer> values = new ArrayList<Integer>(map.values()); 
Collections.sort(values); 
List<Integer> N_values = values.subList(0, N); 
+0

Это сортировкой в ​​HashMap с помощью клавиш (строк), а не значениями –

0

я придумал довольно много то же самое, как это было предложено Стайнар, если вы знаете более LINQ-й/функциональный способ сделать это, пожалуйста, добавьте свой ответ тоже!

//Convert to List of Map.Entry 
ArrayList<Map.Entry<String,Integer>> myArrayList = ArrayList<Map.Entry<String,Integer>>(myHashMap.entrySet()); 

//Natural order is ascending, so we reverse the comparator to get it Descending. 
Collections.sort(myArrayList , Collections.reverseOrder(new EntryComparator())); 

//Create list and add Keys 

List<String> topNStrings = new ArrayList<String>(); 

for (int i = 0; i < N && i < myArrayList.size(); i++) 
{ 
    topNStrings.add(myArrayList.get(i).getKey()); 
} 

и имел отдельный маленький компаратор класс

private class EntryComparator implements Comparator<Map.Entry<String,Integer>> 
    { 
    @Override 
    public int compare(Map.Entry<String,Integer> x, Map.Entry<String,Integer> y) 
    { 
     return compare(x.getValue(), y.getValue()); 
    } 

    private int compare(Integer a, Integer b) 
    { 
     return a < b ? -1 
       : a > b ? 1 
       : 0; 
    } 
} 
Смежные вопросы