Check if Set of Object contain an Object with this

2019-07-25 11:37发布

Consider i have a List Of Objects, and i convert it to a Set to make some actions like this :

List<User> listUser = new ArrayList<>();
listUser.add(new User(1, "user1"));
listUser.add(new User(2, "user2"));
listUser.add(new User(3, "user3"));

Set<User> myset = new HashSet<>(listUser);

I know there are a contains(Object o) but i want to check with the attributes of my Object.

My Question is What is the best way to check if the Set contain an Object with ID = 1 or user = "user1" or any attribute

Thank you.

标签: java set
3条回答
太酷不给撩
2楼-- · 2019-07-25 11:41

Does your User class override equalsusing just the ID? If so, you could use:

if (mySet.contains(new User(1, "irrelevant"));

Note that it's quite odd to have something called mySet which is actually a List rather than a Set... I'd consider either changing the name or the type. If you use HashSet you'll need to override hashCode as well as equals, but you should do that anyway to obey the normal contracts from Object.

If you want to be able to check by multiple different attributes - or if you don't want to override equality in User - then you could consider creating maps instead, e.g.

Map<Integer, User> usersById = new HashMap<>();
Map<String, User> usersByName = new HashMap<>();
...

Then you need to keep all the maps in sync, of course - and you need to consider what happens if you've got multiple users with the same name, etc.

查看更多
beautiful°
3楼-- · 2019-07-25 11:43

You are correct that you cannot use Java streams with Java 7 (they were introduced in Java 8). For Java 7 I would suggest an enhanced for loop in which you check your search condition (if (u.getId() == 1)) and act appropriately.

If you are ever getting a problem with the linear search that the for loop would do, you may build maps: HashMap<Integer, User> for allowing lookup by ID and HashMap<String, User> for lookup by user name. Map.containsKey() will tell you whether the map contains a specific user. You will need to take care that the maps contain all your users, and also that users are removed from the maps when deleted from your set/list, of course (oops, only saw now that Jon Skeet has already said all of this, sorry).

For anyone using Java 8 and reading along here, use of streams needs not be very fancy. A couple of examples:

    boolean containsUser1 = myset.stream().anyMatch(u -> u.getId() == 1);

This yieds true.

    User[] u1Array = myset.stream().filter(u -> u.getId() == 1).toArray(User[]::new);
    Set<User> u1Set = myset.stream().filter(u -> u.getUserName().equals("user1")).collect(Collectors.toSet());

Each of these two yield [1 user1] (the first one as an array, the second as s Set, obviously). Each use of a stream does a linear search behind the scenes.

That said, you can do fancy things with streams. I’ve found it a pleasure learning them and using them, look forward to that.

查看更多
时光不老,我们不散
4楼-- · 2019-07-25 11:55

Simpliest and fanciest way i think is to override equals method in your User class by just considering the id.

Then you can use the contains method from the List interface

查看更多
登录 后发表回答