Java: как преобразовать Список <?> в Карту <Строка?> [дубликат]

Этот вопрос уже имеет ответ здесь:

Я хотел бы найти способ взять объектную определенную стандартную программу ниже и абстрагировать ее в метод, что можно передать класс, список и имя поля для возвращения Карты. Если я мог бы получить общий указатель на используемом шаблоне или, и т.д. который мог бы запустить меня в правильном направлении.

  Map mapped_roles = new HashMap();
    List p_roles = (List) c.list();
    for (Role el :  p_roles) {
        mapped_roles.put(el.getName(), el);
    }

к этому? (Псевдо код)

  Map MapMe(Class clz, Collection list, String methodName)
  Map map = new HashMap();
    for (clz el :  list) {
        map.put(el.methodName(), el);
    }

действительно ли это возможно?

8
задан James P. 7 July 2010 в 13:57
поделиться

5 ответов

Вот что бы я сделал. Я не совсем уверен, правильно ли я обрабатываю дженерики, но да ладно:

public <T> Map<String, T> mapMe(Collection<T> list) {
   Map<String, T> map = new HashMap<String, T>();
   for (T el : list) {
       map.put(el.toString(), el);
   }   
   return map;
}

Просто передайте ему коллекцию, и пусть ваши классы реализуют toString () для возврата имени. Об этом позаботится полиморфизм.

1
ответ дан 3 November 2019 в 12:27
поделиться

Использование Guava (ранее Google Collections):

Map<String,Role> mappedRoles = Maps.uniqueIndex(yourList, Functions.toStringFunction());

Или, если вы хотите поставить свой собственный метод, который делает String из объекта:

Map<String,Role> mappedRoles = Maps.uniqueIndex(yourList, new Function<Role,String>() {
  public String apply(Role from) {
    return from.getName(); // or something else
  }});
33
ответ дан 3 November 2019 в 12:27
поделиться

Использование отражения и дженериков:

public static <T> Map<String, T> MapMe(Class<T> clz, Collection<T> list, String methodName)
throws Exception{
  Map<String, T> map = new HashMap<String, T>();
  Method method = clz.getMethod(methodName);
  for (T el : list){
    map.put((String)method.invoke(el), el);
  }
  return map;
}

Убедитесь, что в вашей документации вы упомянули, что возвращаемый тип метода должен быть String. В противном случае он вызовет исключение ClassCastException, когда попытается преобразовать возвращаемое значение.

1
ответ дан 3 November 2019 в 12:27
поделиться

Если вы уверены, что каждый объект в List будет иметь уникальный индекс, используйте Guava с предложенным Йорном Maps.uniqueIndex.

Если, с другой стороны, более одного объекта могут иметь одинаковое значение для поля index (что, хотя и не верно для вашего конкретного примера, возможно, верно во многих случаях использования такого рода вещей), более общий способ сделать такую индексацию - использовать Multimaps. index(Iterable values, Function keyFunction) для создания ImmutableListMultimap, который сопоставляет каждый ключ с одним или несколькими подходящими значениями.

Вот пример, использующий пользовательскую функцию, которая создает индекс на определенном свойстве объекта:

List<Foo> foos = ...
ImmutableListMultimap<String, Foo> index = Multimaps.index(foos,
    new Function<Foo, String>() {
      public String apply(Foo input) {
        return input.getBar();
      }
    });

// iterate over all Foos that have "baz" as their Bar property
for (Foo foo : index.get("baz")) { ... }
1
ответ дан 3 November 2019 в 12:27
поделиться

Избегайте отражений как чумы.

К сожалению, синтаксис Java для этого многословен. (Недавнее предложение JDK7 сделало бы его гораздо более лаконичным.)

interface ToString<T> {
    String toString(T obj);
}

public static <T> Map<String,T> stringIndexOf(
    Iterable<T> things,
    ToString<T> toString
) {
    Map<String,T> map = new HashMap<String,T>();
    for (T thing : things) {
        map.put(toString.toString(thing), thing);
    }
    return map;
}

В настоящее время он выглядит так:

Map<String,Thing> map = stringIndexOf(
    things,
    new ToString<Thing>() { public String toString(Thing thing) {
        return thing.getSomething();
    }
);

В JDK7 это может быть что-то вроде:

Map<String,Thing> map = stringIndexOf(
    things,
    { thing -> thing.getSomething(); }
);

(Возможно, там понадобится yield.)

3
ответ дан 3 November 2019 в 12:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: