【问题标题】:calling Iterables.contains for a subfield of object list为对象列表的子字段调用 Iterables.contains
【发布时间】:2012-06-06 16:41:48
【问题描述】:

我希望能够测试 List 是否包含具有给定键值的对象

例如,我想做类似 Iterables.contains(l2, "lname", "Jordan")); 之类的事情,而不必像下面在 l2 中创建所有其他 Map 对象

//List<String> l = Arrays.asList("Mickael", "Jordan", "His Airness");
//System.out.println(Iterables.contains(l, "Jordan"));

Map<String, String> p1 = new HashMap<String, String>();
p1.put("fname", "Mickael");
p1.put("lname", "Jordan");
p1.put("nname", "His Airness");

Map<String, String> p2 = new HashMap<String, String>();
p2.put("fname", "Paul");
p2.put("lname", "Pierce");
p2.put("nname", "The Truth");
List<Map<String, String>> l2 = Arrays.asList(p1, p2);
Map<String, String> p3 = new HashMap<String, String>();
p3.put("fname", "Mickael"); //
p3.put("lname", "Jordan");
p3.put("nname", "His Airness"); //
System.out.println(Iterables.contains(l2, p3));

我想知道是否有这样的番石榴的功能,而不是在l2上循环并测试每个elt.get(“lname”)

编辑

回答了 3 个解决方案:尝试查看哪个更高效

System.out.println(Iterables.any(l2, withEntry("lname", "Jordan"))); //@axtavt
System.out.println(has("lname", "Jordan")); //@JB
System.out.println(Iterables.any(l2, new KeyValuePredicate("lname", "Jordan"))); //@JB

public static Boolean has(final String key, final String value) {
    return Iterables.any(l2, new Predicate<Map<String, String>>() {
        @Override
        public boolean apply(Map<String, String> input) {
            return input.get(key).equals(value);
        }
    });
}

public static Predicate<Map<String, String>> withEntry(final String key, final String value) {
    return new Predicate<Map<String, String>>() {
        public boolean apply(Map<String, String> input) {
            return value.equals(input.get(key));
        }
    };
}

class KeyValuePredicate implements Predicate<Map<String, String>>{
private String key;
private String value;
public KeyValuePredicate(String key, String value) {
    super();
    this.key = key;
    this.value = value;
}
@Override
public boolean apply(Map<String, String> arg0) {
    // TODO Auto-generated method stub
    return arg0.get(key).equals(value);
}

}

【问题讨论】:

    标签: java map hashmap guava


    【解决方案1】:
    return Iterables.any(l2, new Predicate<Map<String, String>>() {
        @Override
        public boolean apply(Map<String, String> input) {
            return input.get("lname").equals("Jordan");
        }
    });
    

    但是当您应该使用具有属性的对象时,您正在使用地图。

    当然,如果您需要多次使用各种属性,您应该将谓词转换为非匿名、可重用的类:

    return Iterables.any(l2, new KeyValuePredicate("lname", "Jordan"));
    

    【讨论】:

    • KeyValuePredicate 在我的番石榴版本 (r08) 中似乎不存在
    • Guava 贡献者:@JBNizet 建议您创建自己的 KeyValuePredicate 类,而不是指 Guava 中已有的东西。这绝对是推荐的解决方案,如果(出于某种莫名其妙的原因)您不想遍历列表(尽管您应该这样做,并且您还应该将地图制作成适当的对象,而不是将它们保留为地图)。
    • 就性能而言,简单循环一定更快?
    • Iterables.any 并不神奇。它遍历列表以找到匹配的元素。两者应该相等,或者至少差异可以忽略不计。
    • 如果您想要执行多次查找,您可以通过将列表转换为多图。这样做: Multimap index = Multimaps.index(l2, MapFunctions.get("fname"); assertTrue(!index.get("Jordan").isEmpty()); 你必须自己制作 MapFunctions.get("fname")。但是 JB Nizet 是对的:很可能您想创建类而不是 Map 查找。
    【解决方案2】:

    您可以实现适当的Predicate 并使用Iterables.any()

    public Predicate<Map<String, String>> withEntry(final String key, final String value) {
        return new Predicate<Map<String, String>>() {
            public boolean apply(Map<String, String> input) {
                return value.equals(input.get(key));
            }
        };
    }
    
    System.out.println(Iterables.any(l2, withEntry("lname", "Jordan")));
    

    【讨论】:

    • 效果很好,尝试看看另一种解决方案是否更完善
    【解决方案3】:

    这很简单。

    你应该创建一个合适的实体类:

    public class Person {
    
        private String fName;
        private String lName;
        private String nName;
    
        public Person(String fName, String lName, String nName) {
            this.fName = fName;
            this.lName = lName;
            this.nName = nName;
        }
    
        public String getFName() {
            return fName;
        }
    
        public String getLName() {
            return lName;
        }
    
        public String getNName() {
            return nName;
        }
    
    }
    

    然后您可以执行以下操作:

    import java.util.*;
    public class Test {
    
        public static void main (String [] args) {
    
            List<Person> list = new ArrayList<Person>();
            Person p1 = new Person("Mickael", "Jordan", "His Airness");
    
            for (Person person : list) {
                if (person.getFName().equals("Mickael")) {
                    System.out.println("Mickael is in the list!");
                    break;
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-15
      • 2011-12-21
      • 1970-01-01
      • 2017-06-08
      • 1970-01-01
      • 1970-01-01
      • 2019-11-16
      • 1970-01-01
      • 2022-10-04
      相关资源
      最近更新 更多