# Determine number properties

I am making a program about numbers. The user will enter a number and will get its properties.

### Program objectives

1. Welcome users;
2. Display the instructions;
4. If a user enters zero, terminate the program;
5. If numbers are not natural, print the error message;
6. If an incorrect property is specified, print the error message and the list of available properties;
7. For one number, calculate and print the properties of the number;
8. For two numbers print the list of numbers with their properties;
9. For two numbers and one property print the numbers with this property only;
10. For two numbers and two properties print the numbers that have both properties.
11. If a user specifies mutually exclusive properties, abort the request and warn a user.
12. Once a request has been processed, continue execution from step 3

The property names include even, odd, buzz, duck, palindromic, gapful, spy, square, and sunny.

## The code

package numbers;

import java.util.Scanner;

public class Main {
public static Scanner input = new Scanner(System.in);

public static void main(String[] args) {
Numbers.welcome();
Numbers.request();
while (true) {
System.out.print("Enter a request: ");
String number = input.nextLine();
String[] numberArray = number.split(" ");
if (numberArray.length == 1) {
if (numberArray[0].equals("0")) {
break;
} else {
System.out.println("The first parameter should be a natural number or zero.");
}
Numbers.getPropertiesOfNumber(number);
}
if (numberArray.length == 2) {
if (Numbers.isNatural(Long.parseLong(numberArray[0]))) {
System.out.println("The first parameter should be a natural number or zero.");
continue;
}
if (Numbers.isNatural(Long.parseLong(numberArray[1]))) {
System.out.println("The second parameter should be a natural number.");
continue;
}
long num1 = Long.parseLong(numberArray[0]);
long num2 = Long.parseLong(numberArray[1]);
for (long i = num1; i < num1 + num2; i++) {
Numbers.getPropertiesOfNumberSequence(i);
System.out.println();
}
}
if (numberArray.length == 3) {
if (Numbers.isNatural(Long.parseLong(numberArray[0]))) {
System.out.println("The first parameter should be a natural number or zero.");
continue;
}
if (Numbers.isNatural(Long.parseLong(numberArray[1]))) {
System.out.println("The second parameter should be a natural number.");
continue;
}
String parameter = numberArray[2];
if (!Numbers.requestList.contains(parameter.toUpperCase())) {
StringBuilder errorOutput = new StringBuilder();
errorOutput.append("The property [").append(parameter.toUpperCase()).append("] is wrong.");
errorOutput.append("\nAvailable properties: [").append(Numbers.requestList + "]");
System.out.println(errorOutput);
} else {
long num1 = Long.parseLong(numberArray[0]);
long num2 = Long.parseLong(numberArray[1]);
Numbers.getPropertiesOfNumberWithParameter(num1, num2, parameter);

}

}
if (numberArray.length == 4) {
if (Numbers.isNatural(Long.parseLong(numberArray[0]))) {
System.out.println("The first parameter should be a natural number or zero.");
continue;
}
if (Numbers.isNatural(Long.parseLong(numberArray[1]))) {
System.out.println("The second parameter should be a natural number.");
} else {
long num1 = Long.parseLong(numberArray[0]);
long num2 = Long.parseLong(numberArray[1]);
String parameter1 = numberArray[2].toLowerCase();
String parameter2 = numberArray[3].toLowerCase();
Numbers.checkParameters(num1, num2, parameter1, parameter2);
}
}

}
System.out.println("Goodbye!");
}

}

class Numbers {
public final static String requestList = "BUZZ, DUCK, PALINDROMIC, GAPFUL, SPY, SQUARE, SUNNY, EVEN, ODD";

public static void request() {
StringBuilder output = new StringBuilder();
output.append("\nSupported requests: ");
output.append("\n- enter a natural number to know its properties;");
output.append("\n- enter two natural numbers to obtain the properties of the list:");
output.append("\n  * the first parameter represents a starting number;");
output.append("\n  * the second parameters show how many consecutive numbers are to be processed;");
output.append("\n- two natural numbers and a properties to search for;");
output.append("\n- separate the parameters with one space;");
output.append("\n- enter 0 to exit.\n");
System.out.println(output);

}

public static void welcome() {
System.out.println("Welcome to Amazing Numbers!");
}

public static boolean isNatural(long num) {
return num <= 0;
}

public static boolean isEven(long num) {
return num % 2 == 0;
}

public static boolean isOdd(long num) {
return num % 2 != 0;
}

public static boolean isBuzzNumber(long num) {
return num % 7 == 0 || num % 10 == 7;
}

public static boolean isDuckNumber(long num) {
String number = num + "";
return number.contains("0");
}

public static boolean isPalindromicNumber(long num) {
String number = num + "";
for (int i = 0; i < number.length() / 2; i++) {
if (number.charAt(i) != number.charAt(number.length() - i - 1)) {
return false;
}
}
return true;
}

public static boolean isGapfulNumber(long num) {
String number = num + "";
if (number.length() > 2) {
String str = "";
str += number.charAt(0) + "" + number.charAt(number.length() - 1);
return Long.parseLong(number) % Long.parseLong(str) == 0;
}
return false;
}

public static boolean isSpyNumber(long num) {
String number = num + "";
int sum = 0;
int product = 1;
for (int i = 0; i < number.length(); i++) {
int temp = Integer.parseInt(number.charAt(i) + "");
sum += temp;
product *= temp;
}
return sum == product;
}

public static boolean isSquareNumber(long num) {
long sqrt = (long) Math.sqrt(num);
return sqrt * sqrt == num;
}

public static boolean isSunnyNumber(long num) {
return isSquareNumber(num + 1);
}

public static void getPropertiesOfNumber(String number) {
long num = Long.parseLong(number);
StringBuilder output = new StringBuilder();
if (isNatural(num)) {
System.out.println("The first parameter should be a natural number or zero.");
} else {
output.append("Properties of ").append(number);
output.append("\n\t   buzz: ").append(isBuzzNumber(num));
output.append("\n\t   duck: ").append(isDuckNumber(num));
output.append("\npalindromic: ").append(isPalindromicNumber(num));
output.append("\n\t gapful: ").append(isGapfulNumber(num));
output.append("\n\t\tspy: ").append(isSpyNumber(num));
output.append("\n\t square: ").append(isSquareNumber(num));
output.append("\n\t  sunny: ").append(isSunnyNumber(num));
output.append("\n\t   even: ").append(isEven(num));
output.append("\n\t\todd: ").append(isOdd(num));
System.out.println(output);
}
}

public static void getPropertiesOfNumberSequence(long i) {
StringBuilder output = new StringBuilder();
output.append(i).append(" is");
if (isBuzzNumber(i)) {
output.append(" buzz");
}
if (isDuckNumber(i)) {
output.append(" duck");
}
if (isPalindromicNumber(i)) {
output.append(" palindromic");
}
if (isGapfulNumber(i)) {
output.append(" gapful");
}
if (isSpyNumber(i)) {
output.append(" spy");
}
if (isSquareNumber(i)) {
output.append(" square");
}
if (isSunnyNumber(i)) {
output.append(" sunny");
}
if (isEven(i)) {
output.append(" even");
}
if (isOdd(i)) {
output.append(" odd");
}
System.out.println(output);
}

public static void getPropertiesOfNumberWithParameter(long num1, long num2, String parameter) {
long i = 1;
parameter = parameter.toLowerCase();
while (i <= num2) {
switch (parameter) {
case "buzz":
if (isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
}
num1++;
}

}

public static void getSeveralProperties(long num1, long num2, String parameter1, String parameter2) {
long i = 1;
parameter1 = parameter1.toLowerCase();
parameter2 = parameter2.toLowerCase();
while (i <= num2) {
switch (parameter1) {
case "buzz":
switch (parameter2) {
case "buzz":
if (isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isBuzzNumber(num1) && isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isBuzzNumber(num1) && isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isBuzzNumber(num1) && isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isBuzzNumber(num1) && isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isBuzzNumber(num1) && isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isBuzzNumber(num1) && isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isBuzzNumber(num1) && isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isBuzzNumber(num1) && isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;

}
break;
case "duck":
switch (parameter2) {
case "buzz":
if (isBuzzNumber(num1) && isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isDuckNumber(num1) && isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isDuckNumber(num1) && isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isDuckNumber(num1) && isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isDuckNumber(num1) && isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isDuckNumber(num1) && isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isDuckNumber(num1) && isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;

}
break;
case "palindromic":
switch (parameter2) {
case "buzz":
if (isPalindromicNumber(num1) && isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isPalindromicNumber(num1) && isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isPalindromicNumber(num1) && isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isPalindromicNumber(num1) && isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isPalindromicNumber(num1) && isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isPalindromicNumber(num1) && isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isPalindromicNumber(num1) && isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isPalindromicNumber(num1) && isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;

}
break;
case "gapful":
switch (parameter2) {
case "buzz":
if (isGapfulNumber(num1) && isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isGapfulNumber(num1) && isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isGapfulNumber(num1) && isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isGapfulNumber(num1) && isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isGapfulNumber(num1) && isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isGapfulNumber(num1) && isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isGapfulNumber(num1) && isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isGapfulNumber(num1) && isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;

}
break;
case "spy":
switch (parameter2) {
case "buzz":
if (isSpyNumber(num1) && isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isSpyNumber(num1) && isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isSpyNumber(num1) && isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isSpyNumber(num1) && isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isSpyNumber(num1) && isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isSpyNumber(num1) && isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isSpyNumber(num1) && isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;

}
break;
case "square":
switch (parameter2) {
case "buzz":
if (isSquareNumber(num1) && isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isSquareNumber(num1) && isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isSquareNumber(num1) && isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isSquareNumber(num1) && isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isSquareNumber(num1) && isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isSquareNumber(num1) && isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isSquareNumber(num1) && isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
}
break;
case "sunny":
switch (parameter2) {
case "buzz":
if (isSunnyNumber(num1) && isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isSunnyNumber(num1) && isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isSunnyNumber(num1) && isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isSunnyNumber(num1) && isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isSunnyNumber(num1) && isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isSunnyNumber(num1) && isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isSunnyNumber(num1) && isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
}
break;
case "even":
switch (parameter2) {
case "buzz":
if (isEven(num1) && isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isEven(num1) && isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isEven(num1) && isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isEven(num1) && isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isEven(num1) && isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isEven(num1) && isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isEven(num1) && isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "even":
if (isEven(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
}
break;
case "odd":
switch (parameter2) {
case "buzz":
if (isOdd(num1) && isBuzzNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "duck":
if (isOdd(num1) && isDuckNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "palindromic":
if (isOdd(num1) && isPalindromicNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "gapful":
if (isOdd(num1) && isGapfulNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "spy":
if (isOdd(num1) && isSpyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "square":
if (isOdd(num1) && isSquareNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "sunny":
if (isOdd(num1) && isSunnyNumber(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;
case "odd":
if (isOdd(num1)) {
getPropertiesOfNumberSequence(num1);
i++;
}
break;

}
break;
}
num1++;
}
}

public static void mutuallyExclusiveError(String parameter1, String parameter2) {
System.out.println("The request contains mutually exclusive properties: [" +
parameter1.toUpperCase() + ", " + parameter2.toUpperCase() + "]\n" +
"There are no numbers with these properties.");
}

public static boolean isMutuallyExclusive(String parameter1, String parameter2) {
String[] mutualParameters1 = new String[]{"even odd", "spy duck", "sunny square"};
String[] mutualParameters2 = new String[]{"odd even", "duck spy", "square sunny"};
String parameter = parameter1 + " " + parameter2;
for (int i = 0; i < mutualParameters1.length; i++) {
if (parameter.equals(mutualParameters1[i]) || parameter.equals(mutualParameters2[i])) {
return true;
}
}
return false;
}

public static boolean checkParameter(String parameter) {
String[] parameters = requestList.split(", ");
for (String s : parameters) {
if (parameter.equalsIgnoreCase(s)) {
return false;
}
}
return true;
}

public static void checkParameters(long num1, long num2, String parameter1, String parameter2) {
if (isMutuallyExclusive(parameter1, parameter2)) {
mutuallyExclusiveError(parameter1, parameter2);
} else if (checkParameter(parameter1) && checkParameter(parameter2)) {
System.out.println("The properties [" + parameter1.toUpperCase() + ","
+ parameter2.toUpperCase() + "] are wrong.\n" +
"Available properties: " + "[" + requestList + "]");
} else if (checkParameter(parameter1)) {
System.out.println("The property [" + parameter1.toUpperCase() + "] is wrong.\n" +
"Available properties: [" + requestList + "]");
} else if (checkParameter(parameter2)) {
System.out.println("The property [" + parameter2.toUpperCase() + "] is wrong.\n" +
"Available properties: [" + requestList + "]");
} else {
getSeveralProperties(num1, num2, parameter1, parameter2);
}
}

}


This code works fine.

But I feel I have messed up with this code. E.g. in the getSeveralProperties() method, I have used switch inside switch, and my code became duplicated, not DRY. And there are many more examples. Especially with the get...() methods.

As far as I can understand, you're a beginner lacking some knowledge. But the job is done well. Some considerations:

A perfect code should use identifier names to avoid comments; your code have good names and one unneeded comment at the beginning. But, on the other hand, you have good task description for comments. You can break it into comments, so anyone could find every part of the task in the code.

### Use different classes for different tasks

Your Numbers class does 2 things: output and calculations. In a bigger project, you should break this functionality into several classes.

### Use else if if's are mutually exclusive, and switch if you check one value

if(numberArray.length == 1)
...
else if(numberArray.length == 2)
...


or even

switch(numberArray.length)
case 1:
....


### requestList should be an array

So you shouldn't split it every time. Also, constants are usually named in FULL_UPPER_CASE.

### Turn whiles with known boundaries into fors

long i = 1;
...
while (i <= num2)
{
....
i++;// in every branch
}


is just

for(long i=1; i<=num2; i++)


First, AFAIS, i++ happens in all branches - so you can move it out if switch and do once, before or after. Second, I presume you don't know flag technique, Maps and method references. Still, you can DRY the code. Imagine you've had a method in Numbers:

public static boolean hasNumberProperty(long number, String property)


so hasNumberProperty(10, 'buzz') would call and return isBuzzNumber(10). You see the point, right? All the switches are moved into one small switch, inside this hasNumberProperty. All the big switch-in-switch statement turns into

if(hasNumberProperty(number1, parameter1) and hasNumberProperty(number2, parameter2))
{
getPropertiesOfNumberSequence(num1);
}
i++;


### Some more code cleaning

In checkParameters, checkParameter is called several times with same arguments. This work is redundant, so I'll show you the very secret flag technique:

int parameter1Ok = 0;
if(checkParameter(parameter1))
parameter1Ok = 1;
/*the same for parameter 2*/
...
if(parameter1Ok==1 and parameter2Ok==1)
...
else if(parameter1Ok)


Flags (variables parameter1Ok and parameter2Ok) allow you to save the sign of some property and check it afterwards, without recalculating. Boolean flags are much more common - try to change this code into boolean flags, you will see, why.

E.g. in the getSeveralProperties() method, I have used switch inside switch, and my code became duplicated, not DRY.

You can fix this by creating a Property interface with implementations for even, sunny, etc. Then, rather than using nested switches, you could simply say

for (long i = 1; i < top; i++) {
if (Numbers.holdsAll(number, properties)) {
getPropertiesOfNumberSequence(number);
}
}


I also renamed num1 to number and num2 to top as being more descriptive. I changed from two properties to an arbitrary sized collection. This will also allow you to combine the single case with the pair case as well as allow for future expansion.

public static boolean holdsAll(long number, Iterable<Property> properties) {
foreach (Property property : properties) {
if (!property.isHeldBy(number)) {
return false;
}
}

return true;
}


Note that while I call this an Iterable here, I would probably implement it as an ArrayList when initialized. But the only thing that is required is that it be some form of Iterable so that the foreach works.

An implementation would look like

class Even implements Property {

public function isHeldBy(long number) {
return number % 2 == 0;
}

}


Some time before calling getSeveralProperties, you would have to convert the strings to the properties, but that would be much simpler and would only need done once. Something like

public convertParameterToProperty(String parameter) {
switch (parameter) {
case "even":
return new Even();


Obviously with cases for each type. Or

private static final Map<String, Property> PROPERTY_DICTIONARY = new HashMap<>();

static {
PROPERTY_DICTIONARY.put("even", new Even());


(again entries for each type) with

public static Property convertParameterToProperty(String parameter) {
return PROPERTY_DICTIONARY.get(parameter);
}


Another alternative would be to do the same thing with an enum where each value defines its own isHeldBy method.

These approaches would be much DRYer than what you have now. I.e. my code observation is that you can replace nested switches with either interface implementations or an enum to DRY the code.