9

I have a UserProfile class which contains user's data as shown below:

class UserProfile {

  private String userId;
  private String displayName;
  private String loginId;
  private String role;
  private String orgId;
  private String email;
  private String contactNumber;
  private Integer age;
  private String address;

// few more fields ...

// getter and setter
}

I need to count non null fields to show how much percentage of the profile has been filled by the user. Also there are few fields which I do not want to consider in percentage calculation like: userId, loginId and displayName.

Simple way would be to use multiple If statements to get the non null field count but it would involve lot of boiler plate code and there is another class Organization for which I need to show completion percentage as well. So I created a utility function as show below:

public static <T, U> int getNotNullFieldCount(T t,
        List<Function<? super T, ? extends U>> functionList) {
    int count = 0;

    for (Function<? super T, ? extends U> function : functionList) {
        count += Optional.of(t).map(obj -> function.apply(t) != null ? 1 : 0).get();
    }

    return count;
}

And then I call this function as shown below:

List<Function<? super UserProfile, ? extends Object>> functionList = new ArrayList<>();
functionList.add(UserProfile::getAge);
functionList.add(UserProfile::getAddress);
functionList.add(UserProfile::getEmail);
functionList.add(UserProfile::getContactNumber);
System.out.println(getNotNullFieldCount(userProfile, functionList));

My question is, is this the best way I could count not null fields or I could improve it further. Please suggest.

justAbit
  • 4,166
  • 2
  • 18
  • 34

1 Answers1

8

You can simply a lot your code by creating a Stream over the given list of functions:

public static <T> long getNonNullFieldCount(T t, List<Function<? super T, ?>> functionList) {
    return functionList.stream().map(f -> f.apply(t)).filter(Objects::nonNull).count();
}

This will return the count of non-null fields returned by each function. Each function is mapped to the result of applying it to the given object and null fields are filtered out with the predicate Objects::nonNull.

Tunaki
  • 125,519
  • 44
  • 317
  • 399
  • 2
    @Tom Oh correct, I didn't notice and edited. Thanks! – Tunaki Apr 28 '16 at 11:20
  • 2
    @Tom: this only reflects the inconsistency of the question itself, having “Count null fields” in the title but “count non `null` fields” in its body. – Holger Apr 28 '16 at 11:51
  • 2
    @Holger Thanks for pointing that out, I have updated question title. – justAbit Apr 28 '16 at 12:01
  • 2
    Of course, instead of `.map(f -> f.apply(t)).filter(Objects::nonNull)` you could just write `.filter(f -> f.apply(t)!=null)`, but that’s a matter of taste. – Holger Apr 28 '16 at 12:04