29

我有一组对象。每个对象都有字符串值。

我需要选择所有this值等于“方向”的对象。

是否可以不迭代集合?

4

7 回答 7

30

一般来说,没有。您需要遍历集合并检查每个对象以查看属性是否等于您正在搜索的值。这是一个O(n)操作。

在一种情况下,您可以在不迭代的情况下做到这一点。如果您的对象的equals方法是根据该属性的相等性定义的String,并且该hashCode方法也正确实现,那么您可以使用hashSet.contains及时找到具有正确值的对象,O(1)而无需遍历集合。

正如我所提到的,这是一个非常具体的用例,而不是通用解决方案。如果字符串是某种唯一标识符,它可能会很有用,但它不适用于您的特定用例。

您可能还想考虑其他更适合您的用例的集合。例如,如果您使用 Guava,那么您可以考虑使用Multimap

有关的

于 2012-10-16T07:50:51.250 回答
11

是的,这可以通过覆盖equals()方法来实现。

@Override 
public boolean  equals (Object object) {

}

您只想检查 equals 方法中的所有内容。

代码:

package com.webapp.test;

import java.util.ArrayList;
import java.util.List;

public class EmployeeModel {    

    public EmployeeModel(String name, String designation, long age) {
        this.name = name;
        this.designation = designation;
        this.age = age;
    }

    private String name;
    private String designation;
    private long age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public long getAge() {
        return age;
    }

    public void setAge(long age) {
        this.age = age;
    }

    @Override
    public boolean equals (Object object) {
        boolean result = false;
        if (object == null || object.getClass() != getClass()) {
            result = false;
        } else {
            EmployeeModel employee = (EmployeeModel) object;
            if (this.name == employee.getName() && this.designation == employee.getDesignation() && this.age.equals(employee.getAge())) {
                result = true;
            }
        }
        return result;
    }
}

public static void main(String args[]) {
    EmployeeModel first = new EmployeeModel("Sameer", "Developer", 25);
    EmployeeModel second = new EmployeeModel("Jon", "Manager", 30);
    EmployeeModel third = new EmployeeModel("Priyanka", "Tester", 24);

    List<EmployeeModel> employeeList = new ArrayList<EmployeeModel>();
    employeeList.add(first);
    employeeList.add(second);
    employeeList.add(third);

    EmployeeModel checkUserOne = new EmployeeModel("Sameer", "Developer", 25);
    System.out.println("Check checkUserOne is in list or not ");
    System.out.println("Is checkUserOne Present = ? " + employeeList.contains(checkUserOne));

    EmployeeModel checkUserTwo = new EmployeeModel("Tim", "Tester", 24);
    System.out.println("Check checkUserTwo is in list or not");
    System.out.println("Is checkUserTwo Present = ? " + employeeList.contains(checkUserTwo));

}

输出:

Check checkUserOne is in list or not 
Is checkUserOne Present = ? true
Check checkUserTwo is in list or not 
Is checkUserTwo Present = ? false
于 2014-03-20T12:22:52.463 回答
5

我知道这是一个老问题,但是......

简短的回答:不,这是不可能的......

使用equals()contains()按照其他人的建议应仅限于您用于过滤的属性实际上是对象身份的一部分的情况。除了 O(n) 算法,我没有看到任何方法。

如果你正在考虑原生函数,Java 8 带来了Stream API函数式编程的概念,允许更简单、更清晰的循环调用。尽管如此,值得注意的是,对于您的情况,必须检查集合中的所有对象,因此复杂性将保持为 O(n)。

Java 8 示例stream().filter()

public static void main(String[] args...){
    Set<MyClass> mySet = new HashSet<>();
    mySet.add(new MyClass("Obj 1", "Rio de Janeiro"));
    mySet.add(new MyClass("Obj 2", "London"));
    mySet.add(new MyClass("Obj 3", "New York"));
    mySet.add(new MyClass("Obj 4", "Rio de Janeiro"));

    Set<MyClass> filtered = mySet.stream()
                                 .filter(mc -> mc.getCity().equals('Rio de Janeiro'))
                                 .collect(Collectors.toSet());

    filtered.forEach(mc -> System.out.println("Object: "+mc.getName()));

    // Result:
    //    Object: Obj 1 
    //    Object: Obj 4 
}
于 2017-12-12T12:09:01.130 回答
4

您也可以Predicate在这个问题中使用 like 来过滤列表:过滤 Java 集合的最佳方法是什么?

于 2012-10-16T07:52:09.490 回答
2

你仍然可以使用contains()方法。

您只需要映射您的初始 Set 并将其转换为字符串集合,其中仅包含您想要检查它们是否存在于对象集合中的字段值。

请参阅基于Felipe LeãoMichael Laffargue先前答案的下一个示例。

public static void main(String[] args...){
     Set<MyClass> mySet = new HashSet<>();
     mySet.add(new MyClass("Obj 1"));
     mySet.add(new MyClass("Obj 2"));
     mySet.add(new MyClass("Obj 3"));

     Set<String> mapped = mySet.stream()
                             .map(MyClass::getField())
                             .collect(Collectors.toSet());

     mapped.contains("Obj 1");
     mapped.contains("Obj 2");
     mapped.contains("Obj 4");

     // Result:
     //     true 
     //     true
     //     false

}

于 2019-04-24T14:23:12.063 回答
1

我通过使用Stream API解决了这个问题:

Student ousama = students.stream()
  .filter(student -> "ousama".equals(student.getName()))
  .findAny()
  .orElse(null);

if(ousama != null) {
  //Exist
} else {
  //Doesn't exist
}
于 2021-04-02T17:53:53.037 回答
0

在我的用户类中,我已经初始化了角色变量,例如private Set<\Role> roles; . 这有一个getter方法。在 Role 类中,我有 String 角色变量,它用于存储角色的值。为了得到角色的价值。我可以使用下面的代码。

for (Role role : user.getRoles()) {
           rolevalue = role.getRole();
        }
于 2019-12-27T16:46:27.260 回答