patternjavaModerate
Counting persons in each age range
Viewed 0 times
agecountingeachrangepersons
Problem
I am calculating the number of people within a given age range. This is my current approach.
Note:
The code has been tested and is working. I wanted to know if there is a more efficient approach without using this many if statements?
Note:
- The
personsis aList
- The
getDiffYears()returns the number of years between now and DOB of the person. It includes the month and day as well.
- The method will be returning a
HashMap()(Can be changed if there is a better alternative.)
The code has been tested and is working. I wanted to know if there is a more efficient approach without using this many if statements?
for (Person p: persons) {
Date dob = p.getDob();
if (dob != null) {
years = getDiffYears(p.getDob());
if (years < 10) {
a++;
} else if (years < 20) {
b++;
} else if (years < 30) {
c++;
} else if (years < 40) {
d++;
} else if (years < 50) {
e++;
} else if (years < 60) {
f++;
} else if (years < 70) {
g++;
} else if (years < 80) {
h++;
} else if (years < 90) {
i++;
} else if (years < 100) {
j++;
} else {
k++;
}
} else {
k++;
}
}
map.put("00 - 09", a);
map.put("10 - 19", a);
map.put("20 - 29", b);
map.put("30 - 39", c);
map.put("40 - 49", e);
map.put("50 - 59", f);
map.put("60 - 69", g);
map.put("70 - 79", h);
map.put("80 - 89", i);
map.put("90 - 99", j);
map.put("Unknown", k);Solution
Java 8 streams
Aside from the typos pointed out by @SuperBiasedMan, you can use Java 8's stream-based processing as an alternative for generating your
Other advice
Aside from the typos pointed out by @SuperBiasedMan, you can use Java 8's stream-based processing as an alternative for generating your
Map result.private static final int UPPER_LIMIT = 100;
private static final String[] KEYS = new String[]{ "00 - 09", /* ... */ "Unknown" };
private static int categorize(int year) {
return Math.min(year, UPPER_LIMIT) / 10;
}
Map results = persons.stream()
.map(Person::getDob)
.filter(Objects::nonNull)
.map(ThisClass::getDiffYears)
.map(ThisClass::categorize)
.collect(Collectors.groupingBy(ageCategory -> KEYS[ageCategory],
Collectors.counting()));- Define the
UPPER_LIMITof your age categorization and the desired category names.
- From a
Streamof yourPersonobjects,map()to their birthdays by callingPerson::getDobas method reference.
filter()nullbirthdays by usingObjects::nonNull.
map()birthdays to ages by calling yourgetDiffYears(Date)method. Note that if it is not astaticmethod, the method reference then becomesthis::getDiffYears.
map()ages to the age category by callingcategorize(int)to get the desired array indices forKEYS. If you have not realized yet,ThisClassis just a placeholder for the actual class name.
collect()the age categories into the desiredMapresultgroupingBy()our categorization andcounting()the elements per category.
Other advice
- Your method should return a
Mapinstead ofHashMapso that callers of this method only need to deal with the interface, and not the implementation.
- You may want to consider how to handle for
nullinputs togetDiffYear(Date). Should it return a negative value?
- You can also experiment with deriving the category names in a programmatic manner, instead of using literal
Strings.
- You can even think about making your age categorization depend on a configurable upper limit (100) and band (10). For example, how easy will it be to treat the upper limit as 101 (
UPPER_LIMIT = 101) and a band of 11 years per category (hint: take a closer look at the suggested code...)?
Code Snippets
private static final int UPPER_LIMIT = 100;
private static final String[] KEYS = new String[]{ "00 - 09", /* ... */ "Unknown" };
private static int categorize(int year) {
return Math.min(year, UPPER_LIMIT) / 10;
}
Map<String, Long> results = persons.stream()
.map(Person::getDob)
.filter(Objects::nonNull)
.map(ThisClass::getDiffYears)
.map(ThisClass::categorize)
.collect(Collectors.groupingBy(ageCategory -> KEYS[ageCategory],
Collectors.counting()));Context
StackExchange Code Review Q#116228, answer score: 11
Revisions (0)
No revisions yet.