Обход коллекции Map в порядке добавления элементов
Пытаюсь реализовать метод, который будет конвертировать римские цифры в арабские. Вот код:
public static String convertToRoman(int number) {
Map<String, Integer> roman = new TreeMap<>();
roman.put("M", 1000);
roman.put("CM", 900);
roman.put("D", 500);
roman.put("CD", 400);
roman.put("C", 100);
roman.put("XC", 90);
roman.put("L", 50);
roman.put("XL", 40);
roman.put("X", 10);
roman.put("IX", 9);
roman.put("V", 5);
roman.put("IV", 4);
roman.put("I", 1);
String result = "";
for (Map.Entry<String, Integer> elem : roman.entrySet()) {
int repeat = (int) Math.floor(number / elem.getValue());
number -= repeat * elem.getValue();
result += elem.getKey().repeat(repeat);
}
return result;
}
Как мне организовать обход коллекции в порядке добавления элементов, т.е. чтобы сначала в elem попадал М:1000, потом СМ:900 и т.д.?
Ответы (3 шт):
Никак. Map не хранит порядок добавления элементов. Вам нужно использовать другую структуру данных.
Например LinkedHashMap как подсказали в комментариях.
Если вам важен порядок возможно вам стоит хранить это не как Map, а как объект с двумя полями и так же использовать LinkedList.
В классе Collections есть статический метод singletonMap на такой случай. Можно, например, создать коллекцию List<Map<String, Integer>>:
List<Map<String, Integer>> list = new ArrayList<>();
list.add(Collections.singletonMap("M", 1000));
list.add(Collections.singletonMap("CM", 900));
list.add(Collections.singletonMap("D", 500));
list.add(Collections.singletonMap("CD", 400));
list.add(Collections.singletonMap("C", 100));
list.add(Collections.singletonMap("XC", 90));
list.add(Collections.singletonMap("L", 50));
list.add(Collections.singletonMap("XL", 40));
list.add(Collections.singletonMap("X", 10));
list.add(Collections.singletonMap("IX", 9));
list.add(Collections.singletonMap("V", 5));
list.add(Collections.singletonMap("IV", 4));
list.add(Collections.singletonMap("I", 1));
Открыть по этой коллекции итератор:
Iterator<Map.Entry<String, Integer>> iterator =
list.stream().flatMap(element -> element.entrySet().stream()).iterator();
Обход коллекции итератором:
StringBuilder result = new StringBuilder();
int number = 1822;
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
String key = entry.getKey();
int value = entry.getValue();
int quantity = number / value;
number -= quantity * value;
result.append(key.repeat(quantity));
}
System.out.println(result.toString()); // MDCCCXXII
В данном случае лучше использовать LinkedHashMap, где порядок элементов соответствует порядку их добавления. При последующем изменении существующего значения по ключу порядок остается прежним.
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("M", 1000);
map.put("CM", 900);
map.put("D", 500);
map.put("CD", 400);
map.put("C", 100);
map.put("XC", 90);
map.put("L", 50);
map.put("XL", 40);
map.put("X", 10);
map.put("IX", 9);
map.put("V", 5);
map.put("IV", 4);
map.put("I", 1);
StringBuilder result = new StringBuilder();
int number = 1822;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
int value = entry.getValue();
int quantity = number / value;
number -= quantity * value;
result.append(key.repeat(quantity));
}
System.out.println(result.toString()); // MDCCCXXII