Как сформировать упорядоченный список значений, извлеченных из HashMap?
Вопрос
Моя проблема на самом деле более тонкая, чем предполагает вопрос, но я хотел бы, чтобы заголовок был кратким.
у меня есть HashMap<String, File>
из File
объекты как ценности.Ключи String name
поля, являющиеся частью File
экземпляры.Мне нужно перебрать значения в 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
значения, которые необходимо добавить к StringBuilder
в порядке int fileID
, которое является полем File
сорт.
Надеюсь, я объяснил это достаточно ясно.
Решение
Что-то вроде этого должно работать:
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);
}
});
Другие советы
К сожалению, невозможно получить данные из HashMap в каком-либо распознаваемом порядке.Вам нужно либо поместить все значения в TreeSet с помощью компаратора, который использует fileID, либо поместить их в ArrayList и отсортировать их с помощью Collections.sort, опять же с помощью компаратора, который сравнивает так, как вы хотите.
Метод TreeSet не работает, если есть дубликаты, и это может быть излишним, поскольку вы не собираетесь добавлять или удалять элементы из набора.Метод Collections.sort — хорошее решение для подобных случаев, когда вы собираетесь взять весь HashSet, отсортировать результаты, а затем выбросить отсортированную коллекцию, как только сгенерируете результат.
Хорошо, это то, что я придумал.Кажется, решает проблему, возвращает строку с объектами File, красиво упорядоченными по их идентификаторам файлов.
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();
}
Я никогда раньше не использовал Comparator (относительно новичок в Java), поэтому буду признателен за любые отзывы, если я что-то реализовал неправильно.
Почему бы не собрать их в массив, отсортировать, а затем объединить?
-- МаркусКью
Вам нужно будет добавить свою коллекцию значений() в ArrayList и отсортировать ее с помощью Collections.sort() с помощью специального экземпляра Comparator, прежде чем выполнять итерацию по ней.
Кстати, обратите внимание, что бессмысленно инициализировать StringBuffer размером коллекции, поскольку вы будете добавлять гораздо больше, чем 1 символ на каждый элемент коллекции.
Создайте временный список, затем добавьте в него каждую пару данных.Отсортируйте его с помощью Collections.sort() в соответствии с вашим пользовательским компаратором, и вы получите список в желаемом порядке.
Вот метод, который вы ищете: http://java.sun.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List,%20java.util.Comparator)
Я создавал LinkedHashMap дюжину раз, прежде чем он был добавлен в набор коллекций.
Вероятно, вы захотите создать коллекцию TreeHashMap.
Создание второй коллекции и добавление всего, что добавлено к обеим, на самом деле не является большим достижением, и вы получаете производительность обеих коллекций (затрачивая немного времени при добавлении).
Если вы сделаете это как новую коллекцию, ваш код останется чистым и аккуратным.Класс коллекции должен состоять всего из нескольких строк и должен просто заменить существующую хэш-карту...
Если у вас есть привычка всегда упаковывать свои коллекции, эта штука просто работает, вы даже не думаете об этом.
StringBuffer allFilesString = new StringBuffer(fileCollection.size());
Если весь ваш file.toString() не состоит в среднем из одного символа, вы, вероятно, делаете StringBuffer слишком маленьким.(Если что-то не так, вы можете не устанавливать его и упростить код). Вы можете получить лучшие результаты, если сделаете его несколько кратным размеру.Кроме того, StringBuffer синхронизируется, а StringBuilder нет и здесь более эффективен.
Удалить ненужное 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);
}
});