I have strings of digits ('numbers') that correspond to strings, not all matches are unique, but the numbers are. Nothing changes, it's all constant. Something like this:
10023 - "Hugo" - "Boss"
023 - "Big" - "Boss"
1230 - "Hugo" - "A or B"
// ...and about twenty more like that
what i want, is to be able to receive a string of digits, and then get the two strings for that.
The enum way isn't neat, because i cannot call the enum a number (needs a leading non-digit), otherwise i could go with the whole song-and-dance of defining an enum and then getting the values by looking for the right one with Enum.valueOf()
, and the method way is not neat because it is ugly and unreadable during definition.
public class detailsForNumber {
public String first;
public String second;
public detailsForNumber(String number) {
if (number == "10023") {
first = "Hugo";
second = "Boss";
} else if (number == "023")
//.....and so on
//Then i could later and somewhere else go:
Somewhere.detailsForNumber dFN = Somewhere.detailsForNumber("023");
System.out.println(dFN.first); // Prints 'Big'
is there a readable way to define this relationship somewhere and then a reasonable way to get the strings out of there?
Ideally it would be a non-headache to later add a third string, or have a non-digit character in the 'number', but there will be no changes at runtime.
CodePudding user response:
If it's all constant and static data then you may use a simple switch:
class Name {
private String first;
private String second;
private Name(final String first, final String second) {
this.first = first;
this.second = second;
}
public String getFirst() { return first; }
public String getSecond() { return second; }
public static Name forNumber(final String number) {
switch (number) {
case "10023": return new Name("Hugo", "Boss");
case "023": return new Name("Big", "Boss");
case "1230": return new Name("Hugo", "A or B");
default: return null;
}
}
};
class Main {
public static void main(String args[]) {
final String number = "023";
final Name n = Name.forNumber(number);
if (n == null) {
System.out.println("Not found");
return;
}
System.out.printf("%s -> {%s, %s}\n", number, n.getFirst(), n.getSecond());
}
}
If the data is loaded at runtime, you may use HashMap
.
CodePudding user response:
I would go with creating a class that has three attributes.
key
of typeString
(the leading zero unique numbers that you have)str1
theString
value 1str2
theString
value 2
And then create another class
that keeps all your Data. You can then filter using streams.
For example:
public class Data
{
private String key;
private String str1;
private String str2;
// Getters, setters, equals...
}
public class DataList
{
private List<Data> list = new ArrayList<>();
public boolean addDataToList(Data newData)
{
boolean isDuplicate = list.stream().anyMatch(data -> data.getKey().equals(newData.getKey()));
if(isDuplicate)
{
return false;
}
list.add(newData);
return true;
}
public Data getThroughKey(String key)
{
Optional<Data> opt = list.stream().filter(data -> data.getKey().equals(key)).findFirst();
// Or handle it
return opt.orElse(null);
}
// Getters, setters and whatever else you need
}
You could also use a Set
which takes care of duplicates without you explicitly checking. But you must override the equals()
and hashCode()
functions in your Data
class.
I do not know which one of them is more efficient. That's a story for another question.
CodePudding user response:
Try this.
public enum DetailsForNumber {
E10023("10023", "Hugo", "Boss"),
E023("023", "Big", "Boss"),
E1230("1230", "Hugo", "A or B");
public final String number, first, second;
private static final Map<String, DetailsForNumber> map = new HashMap<>();
static {
for (DetailsForNumber e : values())
map.put(e.number, e);
}
private DetailsForNumber(String number, String first, String second) {
this.number = number;
this.first = first;
this.second = second;
}
public static DetailsForNumber get(String number) {
return map.computeIfAbsent(number,
k -> { throw new IllegalArgumentException("number"); });
}
}
public static void main(String[] args) {
DetailsForNumber dFN = DetailsForNumber.get("023");
System.out.println(dFN.first);
}
output:
Big
CodePudding user response:
using enum
like below:
public enum NumberDetails {
// it's a demo, you can define the name more meaningful.
NUMBER_1("10023", "Hugo", "Boss"),
NUMBER_2("023", "Big", "Boss"),
NUMBER_3("1230", "Hugo", "A or B");
private String number;
private String first;
private String second;
static Map<String, NumberDetails> CACHE_MAP = Arrays.stream(values())
.collect(Collectors.toMap(NumberDetails::getNumber, it -> it, (a, b) -> a));
public static NumberDetails from(String number) {
return CACHE_MAP.get(number);
}
NumberDetails(String number, String first, String second) {
this.number = number;
this.first = first;
this.second = second;
}
public String getNumber() {
return number;
}
public String getFirst() {
return first;
}
public String getSecond() {
return second;
}
}
and a simple usage:
public class NumberDetailsTest {
public static void main(String[] args) {
System.out.println(NumberDetails.from("023").getFirst());
}
}