Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:如何转换列表<&燃气轮机;到地图<;字符串,?gt;_Java_Generics_List_Map - Fatal编程技术网

Java:如何转换列表<&燃气轮机;到地图<;字符串,?gt;

Java:如何转换列表<&燃气轮机;到地图<;字符串,?gt;,java,generics,list,map,Java,Generics,List,Map,我想找到一种方法来获取下面特定于对象的例程,并将其抽象为一个方法,您可以通过传递类、列表和字段名来获取映射。 如果我能得到一个关于所使用的模式的通用指针,或者等等,这可以让我朝着正确的方向开始 Map<String,Role> mapped_roles = new HashMap<String,Role>(); List<Role> p_roles = (List<Role>) c.list(); for (Role el :

我想找到一种方法来获取下面特定于对象的例程,并将其抽象为一个方法,您可以通过传递类、列表和字段名来获取映射。 如果我能得到一个关于所使用的模式的通用指针,或者等等,这可以让我朝着正确的方向开始

  Map<String,Role> mapped_roles = new HashMap<String,Role>();
    List<Role> p_roles = (List<Role>) c.list();
    for (Role el :  p_roles) {
        mapped_roles.put(el.getName(), el);
    }
Map-mapped_-roles=new HashMap();
List p_roles=(List)c.List();
对于(角色el:p_角色){
映射的_roles.put(el.getName(),el);
}
这个?(伪代码)

映射映射ME(类clz、集合列表、字符串方法名)
Map Map=newhashmap();
对于(clz el:列表){
map.put(el.methodName(),el);
}

有可能吗?

使用反射和泛型:

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;
}
publicstaticmapmapme(类clz,集合列表,stringmethodname)
抛出异常{
Map Map=newhashmap();
Method=clz.getMethod(methodName);
对于(T el:列表){
map.put((String)method.invoke(el),el);
}
返回图;
}

在您的文档中,请确保提到方法的返回类型必须是字符串。否则,它将在尝试强制转换返回值时抛出ClassCastException。

下面是我要做的。我不完全确定我是否正确处理泛型,但哦,好吧:

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;
}
公共地图映射(集合列表){
Map Map=newhashmap();
对于(T el:列表){
map.put(el.toString(),el);
}   
返回图;
}

只需向其传递一个集合,并让您的类实现toString()以返回名称。多态性会解决它。

避免像瘟疫一样的反射

不幸的是,Java的语法非常冗长。(最近的JDK7提案将使其更具考虑性。)

与字符串的接口{
字符串到字符串(T obj);
}
公共静态映射stringIndexOf(
难以忍受的事情,
ToString ToString ToString
) {
Map Map=newhashmap();
对于(T事物:事物){
地图放置(toString.toString(东西),东西);
}
返回图;
}
目前称为:

Map<String,Thing> map = stringIndexOf(
    things,
    new ToString<Thing>() { public String toString(Thing thing) {
        return thing.getSomething();
    }
);
Map Map=stringIndexOf(
东西,
new-ToString(){public-String-ToString(Thing){
return thing.getSomething();
}
);
在JDK7中,它可能类似于:

Map<String,Thing> map = stringIndexOf(
    things,
    { thing -> thing.getSomething(); }
);
Map Map=stringIndexOf(
东西,
{thing->thing.getSomething();}
);
(可能需要一个
产量

使用:


如果您确定
列表中的每个对象都有一个唯一的索引,请与Jorn建议的
Maps.uniqueIndex
一起使用

另一方面,如果多个对象的索引字段可能具有相同的值(这对于您的特定示例来说可能不是真的,但在这类事情的许多用例中却是真的),更通用的索引方法是创建一个
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")) { ... }
listfoos=。。。
ImmutableListMultimap index=Multimaps.index(foos,
新函数(){
公共字符串应用(Foo输入){
返回input.getBar();
}
});
//迭代所有以“baz”作为其Bar属性的foo
for(Foo-Foo:index.get(“baz”){…}

Java8流和方法引用使这变得非常简单,您不需要助手方法

Map<String, Foo> map = listOfFoos.stream()
    .collect(Collectors.toMap(Foo::getName, Function.identity()));
Map Map=listofoos.stream()
.collect(Collectors.toMap(Foo::getName,Function.identity());
如果可能存在重复键,则可以使用聚合值,也可以使用收集到列表中:

//taken right from the Collectors javadoc
Map<Department, List<Employee>> byDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment));
//取自javadoc
Map byDept=employees.stream()
.collect(Collectors.groupingBy(雇员::getDepartment));
如上所示,这些都不是字符串特有的——您可以在任何类型上创建索引

如果要处理大量对象和/或索引功能很昂贵,可以使用
Collection.parallelStream()
stream().parallel()
()。在这种情况下,您可以使用或,因为它们允许流实现只将元素爆炸到ConcurrentMap中,而不是为每个线程创建单独的映射,然后合并它们


如果您不想提交到
Foo::getName
(或任何特定方法)在调用站点,您可以使用调用方传入的、存储在字段中的函数等。实际创建该函数的人仍然可以利用方法引用或lambda语法。

@Aircule:在这里可以使用旧的functor hack。我不明白。您想要一个
x
事物的列表,并将其转换为映射,其中键是对象名,值是对象名?对,键是从传递的方法返回的字符串值(object Person拥有方法名(),Person name成为键),值是对象本身。比较字符串要比手头有对象进行比较容易得多。像这样的时候+1我希望有一个“最喜欢的答案”选项。完美,这是有意义的。谢谢-1-这可能在好的一天起作用,但它很脆弱…而且可能比原始代码昂贵得多。没有合理的理由这样做,只需使用函数而不是reflection@mangst-它会中断(没有编译错误)如果程序员传递了错误的名称,或者方法的签名发生了变化,或者列表签名发生了变化……我喜欢使用此vs反射的想法,我必须同时实现这两种方法。谢谢,这只适用于
toString()
作为获取索引键的函数,它不是一个很好的通用解决方案,显然不适用于对象的任何任意属性。反射解决方案更糟糕,在重构时没有编译器错误。在这种情况下,您可以使用公共静态映射。BaseModel包含字段id和
Map<String,Role> mappedRoles = Maps.uniqueIndex(yourList, new Function<Role,String>() {
  public String apply(Role from) {
    return from.getName(); // or something else
  }});
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")) { ... }
Map<String, Foo> map = listOfFoos.stream()
    .collect(Collectors.toMap(Foo::getName, Function.identity()));
//taken right from the Collectors javadoc
Map<Department, List<Employee>> byDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment));