lambda - Filter Java Stream to 1 and only 1 element -


i trying use java 8 streams find elements in linkedlist. want guarantee, however, there 1 , 1 match filter criteria.

take code:

public static void main(string[] args) {      linkedlist<user> users = new linkedlist<>();     users.add(new user(1, "user1"));     users.add(new user(2, "user2"));     users.add(new user(3, "user3"));      user match = users.stream().filter((user) -> user.getid() == 1).findany().get();     system.out.println(match.tostring()); }  static class user {      @override     public string tostring() {         return id + " - " + username;     }      int id;     string username;      public user() {     }      public user(int id, string username) {         this.id = id;         this.username = username;     }      public void setusername(string username) {         this.username = username;     }      public void setid(int id) {         this.id = id;     }      public string getusername() {         return username;     }      public int getid() {         return id;     } } 

this code finds user based on id. there no guarantees how many users matched filter.

changing filter line to:

user match = users.stream().filter((user) -> user.getid() < 0).findany().get(); 

will throw nosuchelementexception (good!)

i throw error if there multiple matches, though. there way this?

technically there's ugly 'workaround' involves peek() , atomicinteger, shouldn't using that.

what in these cases collecting in list, this:

linkedlist<user> users = new linkedlist<>(); users.add(new user(1, "user1")); users.add(new user(2, "user2")); users.add(new user(3, "user3")); list<user> resultuserlist = users.stream()         .filter(user -> user.getid() == 1)         .collect(collectors.tolist()); if (resultuserlist.size() != 1) {     throw new illegalstateexception(); } user resultuser = resultuserlist.get(0); 

i not aware of way in api, meanwhile work on example involving custom element.

update, should create own collector this:

public static <t> collector<t, list<t>, t> singletoncollector() {     return collector.of(             arraylist::new,             list::add,             (left, right) -> { left.addall(right); return left; },             list -> {                 if (list.size() != 1) {                     throw new illegalstateexception();                 }                 return list.get(0);             }     ); } 

what is:

  • it mimicks collectors.tolist() collector.
  • it applies finisher @ end, throws exception, or if no exception, returns first element of list.

used as:

user resultuser = users.stream()         .filter(user -> user.getid() > 0)         .collect(singletoncollector()); 

you can customize singletoncollector as want, example give exception argument in constructor, tweak allow 2 values, , more.

new update, revised old answer once more singletoncollector(), can obtained this:

public static <t> collector<t, ?, t> singletoncollector() {     return collectors.collectingandthen(             collectors.tolist(),             list -> {                 if (list.size() != 1) {                     throw new illegalstateexception();                 }                 return list.get(0);             }     ); } 

Comments

Popular posts from this blog

c++ - llvm function pass ReplaceInstWithInst malloc -

Cross-Compiling Linux Kernel for Raspberry Pi - ${CCPREFIX}gcc -v does not work -

java.lang.NoClassDefFoundError When Creating New Android Project -