Related
I have a method (shown below) which works fine. The purpose of this method is to confirm if a specific item is available in a shop, with a return value of true or false.
I have a second method, which returns a description, but I can't see to work out how to get this method to pull through the first method response with 'true' showing as 'Yes' or 'false' showing as 'No'. I'm assuming it is something to do with method calling and string concatenation.
My overall problem pulls through 2 methods, but I wanted to just try and understand how to pull one method first and then I'll hopefully work out the rest!
Method 1
public void isFree()
{
if (sweet.isEmpty()){
System.out.println("True");
}
else {
System.out.println("False");
}
}`
Method 2
public void information()
{
System.out.println (isFree+ " this item is available for purchase.");
}
Return type of your first method is void so you are not returning anything, you are just printing Yes or False in new line. To concatanate "True" or "False" to another String you need to return String from isFree method
You may try something like this
public String isFree(){
return sweet.isEmpty() ? "True" : "False";
}`
public void information(){
System.out.println (isFree() + " this item is available for purchase.");
}
In second method message doesnt make much sense with False but this is up to you to adjust it
You can also reutrn boolean directly
public boolean isFree() {
return sweet.isEmpty();
}
Keep in mind that in this case it will be revolved to "true" or "false" and not "True"/"False"
Of course if "true"/"false" is ok in your case you can remove isFree method completly and just use sweet.isEmpty() directly in information
Is there any specific reason to use two methods, rather isEmpty in the collection will return the boolean (true, false) for you and you can directly use the second method removing the first completely.
public void information() {
String customText=", this item is available for purchase.";
System.out.println (sweet.isEmpty() ? "YES"+customText : "NO"+customText);}
You can achieve this from several ways:
Call first isFree from information, and then print the second string. For this, you would have to edit both methods, since you are using println.
public void isFree() {
sweet.isEmpty() ? System.out.printf("True") : System.out.printf("False");
}
public void information() {
isFree();
System.out.printf(" this item is available for purchase.\n");
}
Make isFree return a String.
public String isFree() {
sweet.isEmpty() ? "True" : "False";
}
public void information() {
System.out.println(isFree() + " this item is available for purchase.");
}
I have a object and i get some fields from it, i made a method with a switch statement, the idea was make it generic and just call this method through parameters but now I´m not sure.
The options are
private String getCode(Row row, String code) {
String result;
switch (code) {
case code1:
result = row.getString("constant1");
break;
case code2:
result = row.getString(constant2);
break;
case code3:
result = row.getString(constant3);
break;
case code4:
result = row.getString(constant4);
break;
default:
result = null;
}
return result;
}
or
private String getcode1(Row row){
return row.getString("constant1")
}
private String getcode1(Row row){
return row.getString("constant2")
}
private String getcode1(Row row){
return row.getString("constant3")
}
private String getcode1(Row row){
return row.getString("constant4")
}
I wand to use the better way, I´m a little confuse
The answer is neither of the them.
What you have here is a value conversion process. How this works? Well, as far I understand, you need to store the data in form of key-value pair where key must be unique. So this is the definition of a HashMap in java.
Also, because you are using Switch I'm assuming that you can identify your data with some unique key. This meas for each code there is only one constant. But how we can apply this to my issue? Well, I think you have a collection of data from where you extracted a single row. Now, from this row you want to access to a value (lets call it codeValue) using a constant, but to get this constant you need a code. Like this: code->constant->codeValue
How can I implement this??
Well, we gonna need a HasMap() called constants, which defines its keys a codes and the values as constants. Now you easily get each constant if you know its code. Obviously, if you get the constant you can also get the codeValue of each `row, like this:
public class TestClass {
public static void main(String[] args) {
// Create a HashMap object called constants
Map<String, String> constants = new HashMap<String, String>();
// Add keys and values (code, constant)
constants.put("code1", "constant1");
constants.put("code2", "constant2");
constants.put("code3", "constant3");
constants.put("code4", "constant4");
System.out.println(constants);
Row row = loadRow();
String code = loadCode();
//How to use it
String result = getCodeValue(row, code);
System.out.println(result);
}
// Now you get the code from the Map
private String getCodeValue(Row row, String code) {
return row.getString(constants.get(code));
}
}
In case your input code is different than constant, I will suggest the following approach. Create an Enum mapping code and constant.
public enum Mapping {
MAPPING_FIRST("code1", "constant1"),
MAPPING_SECOND("code2", "constant2");
private String code;
private String constant;
// constructor and getters
public static Mapping getMappingFromCode(String code){
return Arrays.stream(Mapping.values())
.filter(mapping -> mapping.getCode().equals(code))
.findFirst()
.orElse(null);
}
}
Now, create a method to access value from row.
private String getValue(Row row, String code) {
Mapping mapping = Mapping.getMappingFromCode(code);
if(mapping == null){
return null;
}
return row.getString(mapping.getConstant());
}
This question is little bit to much, but I will try to explain best I could. For me second option is no no at all. Why? You are making methods that you will have to sort out with some if/else statements anyway, for example:
if (code.equals(code1))
someString = getcode1(row);
else if (code.equals(code2))
somestring = getcode2(row);
else if (code.equals(code3))
someString = getcode3(row);
else
someString = getcode4(row);
Why not use this:
if (code.equals(code1))
someString = row.getString("content1");
else if (code.equals(code2))
somestring = row.getString("content2");
else if (code.equals(code3))
someString = row.getString("content3");
else
someString = row.getString("content4");
The first one I can see being used, but there is alternative there. Give us entire minimal requirement code with entire class and methods and we could help you far more than using these snippets of code.
Create an enum for mapping of code and constant. In that enum, create a generic method where you can get code just passing through parameter.
public enum MyEnum {
CODE1("constant1"), CODE2("constant2");
private String constant;
public String getConstant() {
return constant;
}
private MyEnum(String constant) {
this.constant = constant;
}
private static String getConstant(String code) {
return Arrays.stream(MyEnum.values()).filter(mapping -> mapping.name().equalsIgnoreCase(code))
.map(e -> e.getConstant()).findAny().orElse(null);
}
public static String getCode(Row row, String code) {
String constant = getConstant(code);
return constant != null ? row.get(constant) : null;
}
}
You can get code from row object by calling genric method getCode().
MyEnum.getCode(row, "code1")
I have multiple conditions to check as shown below,
if(pouch.getStatus().equals("Finalized") || pouch.getStatus().equals("Ready")
|| pouch.getStatus().equals("Checkout") || pouch.getStatus().equals("Confirmed")
|| pouch.getStatus().equals("Book") || pouch.getStatus().equals("Started")
|| pouch.getStatus().equals("Inital") || pouch.getStatus().equals("Close")) {
// Body Implementation
}
Is there any easy way to check above conditions similar like SQL INcondition, so that code look simpler?
Let's take a look about SQL in features
SQL WHERE IN returns values that match values in a list
So I would use a collection, which implements from Collection<E> and had contains method, make the if statement simpler.
contains(Object o) Returns true if this set contains the specified element.
contains effect is very similar to SQL in.
1.add your multiple conditions in the collection, which implements from Collection<E>
Set<String> dict = new HashSet<String>();
dict.add("Finalized");
dict.add("Ready");
dict.add("Checkout");
dict.add("Confirmed");
dict.add("Book");
dict.add("Started");
dict.add("Inital");
dict.add("Close");
2.using contains to check input value whether exist in the collection.
if (dict.contains(pouch.getStatus()))
{
// do your logic
}
You can use the method matches which is available in String class,
if(pouch.getStatus().matches("Finalized|Ready|Checkout|Confirmed|Book|Started|Inital|Close")){
//your implementation goes here
}
List<String> listOfInputs = new ArrayList<String>();
// add elements in listOfInputs...
boolean isAvailable = listOfInputs.contains(pouch.getStatus());
SQL IN might return more than one result, but in your question, if one condition is satisfied the operation will terminate and return.
You can create an enum to hold all your conditions as shown below.
Assuming your Pouch class is this.
public class Pouch {
private final String status;
public Pouch(final String status) {
this.status = status;
}
public String getStatus() {
return status;
}
}
Here is your enum with the pouch status.
public enum PouchEnum {
Finalized, Ready, Checkout, Confirmed, Book, Started, Inital, Close
}
and check your condition as shown below.
if (PouchEnum.valueOf(pouch.getStatus()) != null) {
// Do some stuff
}
To make it cleaner you can use EnumUtils from apache commons-lang3 this make your code checking more cleaner as shown below.
if (EnumUtils.isValidEnum(PouchEnum.class, pouch.getStatus())) {
// Do some stuff
}
I hope this will help your code to be cleaner.
You can create custom function:
static boolean inCondition(String var, String... ins) {
for (String in : ins) {
if (in.equals(var)) return true;
}
return false;
}
and then use it in this way:
public static void main(String[] args) {
String pouch = "Ready";
if (inCondition(pouch, "Finalized", "Ready", "Checkout" ... )) {
// do something
}
}
Below snippet might help you.
String status = "COMPLETED";
List<String> statusList = new ArrayList<>(Arrays.asList("COMPLETED","INPROGRESS"));
if(statusList.contains(status)){
// do your stuff
}
Using Arrays.asList and then use contains might be the best way at least on my case.
if(Arrays.asList("Finalized", "Ready", "Checkout", "Confirmed",
"Book", "Started", "Inital", "Close").contains(pouch.getStatus())) {
// Body
}
I think if you use the "switch" conditional, the code reads better:
switch (pouch.getStatus()) {
case "Finalized":
case "Ready":
case "Checkout":
case "Confirmed":
case "Book":
case "Started":
case "Inital":
case "Close":
// your code
break;
}
For this particular scenario, I think it's a good candidate for a simple enum like this:
public enum PouchStatus {
FINALIZED, READY, CHECKOUT, CONFIRMED, BOOK, STARTED, INITIAL, CLOSE
}
Usage:
if(PouchStatus.valueOf(pouch.getStatus().toUpperCase()) != null) {
}
You can also move this string sanitizing logic inside a static method in the enum, which would look like this:
public enum PouchStatus {
FINALIZED, READY, CHECKOUT, CONFIRMED, BOOK, STARTED, INITIAL, CLOSE
public static PouchStatus fromDescription(String desc) {
return Arrays.stream(PouchStatus.values()).filter(e -> e.name().equalsIgnoreCase(desc)).findFirst().orElse(null);
}
}
Usage:
if (PouchStatus.fromDescription(pouch.getStatus()) != null) {
}
As a final note, if the Pouch object comes from ORM (e.g.: hibernate/jpa) you can just map these values to the according enum elements right in the entity mapping (pouc.getStatus() would already return a PouchStatus object instead of a String).
Here is full example
public class InConditionJava {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] arr = { "Finalized", "Ready", "Checkout" };
checkData(arr);
}
private static void checkData(String[] arr) {
Set<String> names = new HashSet<String>(Arrays.asList(arr));
System.out.println("AS Checkout is there in our arr is should return True>>" + names.contains("Checkout")); // true
System.out.println(names.contains("Book")); // false
}
}
Here is another way of initializing List in one line with all statuses, and then checking if the list contains the given status.
// Java 9 way of initializing List with one line
List<String> statuses = List.of("Finalized", "Ready", "Checkout", "Confirmed",
"Book", "Started", "Inital", "Close");
if (statuses.contains(pouch.getStatus())) {
// Body
}
You can create an array of all status, then check if pouch.getStatus() in in that list or not?
public String[] statusArray = new String[]{ "Finalized", "Ready","Checkout","Confirmed", "Book", "Started", "Inital", "Close"};
if( Arrays.asList(statusArray).contains(pouch.getStatus())){
//do something
}
There are already plenty of options here, but you could also use Stream for this task, if the version of the JDK you are using is >= 8:
String status = pouch.getStatus();
if (Stream.of(
"Finalized",
"Ready",
"Checkout",
"Confirmed",
"Book",
"Started",
"Inital",
"Close")
.anyMatch(status::equals)) {
// Body
}
The downside of this method, compared to Collection#contains, is that you must make sure that pouch.getStatus() is not null, otherwise you will get a NullPointerException.
I am getting a warning that watchStore.contains(s) is a suspicious call to java.util.Collection#contains. How can I fix it? I want to use contains() to find a particular object with the matching serial number.
public Watch findWatchBySerialNumber(long srch) {
long s = srch;
Watch watch = null;
for(int i = 0; i < watchStore.size(); i++) {
watch = watchStore.get(i);
if(watchStore.contains(s)) {
System.out.print("item found");
return watch;
}
}
System.out.print("item not found");
return null; // watch is not found.
}
Presuming that Watch is the class, watchStore is a List<Watch>, and that a field serialNo exists on Watch...
public Optional<Watch> findWatchBySerialNumber(long serial) {
return watchStore.stream()
.filter(w -> w.getSerialNo() == serial)
.findFirst();
}
If you're not using Java 8, the code is close, but a bit more dangerous since you have the chance to return null. If you can use Guava's Optional, that'd be a better choice here.
public Watch findWatchBySerialNumber(long serial) {
for(Watch w : watchStore) {
if(w.getSerialNo() == serial) {
return w;
}
}
return null;
}
Your contains isn't going to work since your list doesn't contain Longs, it contains Watchs. This is also why the compiler sees it as dubious; contains accepts an Object but it will return false if what you're looking for doesn't have a comparable equals for what's in your list.
You have to iterate over the entirety of your collection to find it in this scenario, especially since you're looking for a specific property on those objects as opposed to a specific, easy-to-provide value.
please how can I fix that. I want to use the contain() to find a
particular object with the matching serial number.
In that case override Watch's equals() to use serialNumber field for comparison.
Then add constructor that accepts serialNumber.
public class Watch {
private final long serialNumber;
public Watch(long serialNumber) {
this.serialNumber = serialNumber;
}
#Override
public boolean equals(Object obj) {
return obj == this ||
(obj instanceof Watch && ((Watch)obj).serialNumber == serialNumber);
}
#Override
public int hashCode() {
return (int)serialNumber;
}
}
Replace if(watchStore.contains(s)){ with if(watchStore.contains(watchToFind)){ where Watch watchToFind = new Watch(s);
you can use contains method from org.apache.commons.lang.ArrayUtils package.
Checks if the value is in the given array.
The method returns false if a null array is passed in.
Parameters:
array the array to search through
valueToFind the value to find
Returns:
true if the array contains the object
long [] imageHashes= {12l,13l,14l,15l};
System.out.println(ArrayUtils.contains(imageHashes, 13l));
I want to write a method in Java that verifies that some conditions hold on some data, and acknowledges that the data is valid or produces an appropriate error message otherwise.
The problem is that we cannot return more than one thing from a method, so I'm wondering what the best solution is (in terms of readability and maintainability).
First solution. Easy, but we cannot know what exactly made the check fail:
boolean verifyLimits1(Set<Integer> values, int maxValue) {
for (Integer value : values) {
if (value > maxValue) {
return false; // Out of limits
}
}
return true; // All values are OK
}
Second solution. We have the message, but we are using exceptions in a way that we shouldn't (besides, it should probably be a domain-specific checked exception, too much overhead IMO):
void verifyLimits2(Set<Integer> values, int maxValue) {
for (Integer value : values) {
if (value > maxValue) {
throw new IllegalArgumentException("The value " + value + " exceeds the maximum value");
}
}
}
Third solution. We have a detailed message, but the contract is not clean: we make the client check whether the String is empty (for which he needs to read the javadoc).
String verifyLimits3(Set<Integer> values, int maxValue) {
StringBuilder builder = new StringBuilder();
for (Integer value : values) {
if (value > maxValue) {
builder.append("The value " + value + " exceeds the maximum value/n");
}
}
return builder.toString();
}
Which solution would you recommend? Or is there a better one (hopefully!)?
(Note: I made up this little example, my real use case concerns complex conditions on heterogeneous data, so don't focus on this concrete example and propose Collections.max(values) > maxValue ? "Out of range." : "All fine." :-).)
If you need more than a single value you should return a simple class instance instead. Here is an example of what we use in some cases:
public class Validation {
private String text = null;
private ValidationType type = ValidationType.OK;
public Validation(String text, ValidationType type) {
super();
this.text = text;
this.type = type;
}
public String getText() {
return text;
}
public ValidationType getType() {
return type;
}
}
This uses a simple Enumeration for the type:
public enum ValidationType {
OK, HINT, ERROR;
}
A validator method could look like this:
public Validation validateSomething() {
if (condition) {
return new Validation("msg.key", ValidationType.ERROR);
}
return new Validation(null, ValidationType.OK);
}
That's it.
The solution is simple: create a custom VerificationResult class. It can have a boolean status flag and a String message field, among other things you may want to add. Instead of returning either a String or a boolean, return a VerificationResult.
Also, depending on context, throwing an exception may actually end up being the right thing to do. This has to be considered on a case-by-case basis based on concrete scenarios, though.
Alternative solution: a last error query
Another option you can use is to have the verification return a boolean, and have a separate method e.g. String whatWentWrongLastTime() that a user can query in case false is returned. You'd have to be very careful with any concurrency issues etc. that may overwrite the "last" verification error.
This is the approach taken by e.g. java.util.Scanner, which does NOT throw any IOException (except for the constructors). To query if something "went wrong", you can query its ioException() method, which returns the last IOException, or null if there wasn't any.
IllegalArgumentException is the way to go if it really means that: You make some demands to the caller of the method (the contract) but they are ignored. In this case an IAE is appropriate.
If that doesn't reflect your use case, I'd use one of the solutions of the others.
Another approach - use a Status object:
public class Status {
public final static Status OK = new Status("OK");
private String message;
public Status(String message) { this.message = message; }
public String getMessage() { return message; }
}
To Verify, either return Status.OK if the input is valid or create a new Status message.
public Status validate(Integer input, int maxValue){
if (input > maxValue) {
return new Status(
String.format("%s value out of limits (maxValue=%s)", input, maxValue);
}
return Status.OK;
}
Using the verifier is simple as that:
Status status = validate(i, 512);
if (status != Status.OK) {
// handle the error
}
I think the best solution is to create your own exception that holds as much error description information as you want. It should not be a RuntimeException subclass; you want callers to have to deal with a failure to validate, because too many programmers fail to put in error handling. By making failure a checked exception, you force them (you?) to put at least something in, and code review can relatively easily pick up if they're being stupid about it. I know it's bureaucratic, but it improves code quality in the long run.
Once you've done that, consider whether you need to return a value on successful validation or not. Only return a value if that value contains information other than “oh, I've got here now” (which is obvious from the program flow). If you do need to return a result, and it needs to be a complex result, by all means use a custom class instance to hold it! To not do that is just refusing to use the facilities that the language gives you.
In this case, the method returning 'false' looks like a business logic result rather than a real Exception. So verifyLimits should return a result anyway rather than throwing an Exception when 'false'.
class VerifyLimitsResult{
//Ignore get, set methods
Integer maxValue;
Integer value;
public VerifyLimitsResult(Integer maxValue, Integer value) {
this.maxValue = maxValue;
this.value = value;
}
public boolean isOK(){
return value==null;
}
public String getValidationInfo(){
if(isOK()){
return "Fine";
}else{
return "The value " + value + " exceeds the maximum value/n"
}
}
}
....
VerifyLimitsResult verifyLimits4(Set<Integer> values, int maxValue) {
for (Integer value : values) {
if (value > maxValue) {
return new VerifyLimitsResult(maxValue, value);
}
}
return new VerifyLimitsResult(maxValue, null);
}
If you check a reasonable amount of items and be concerned about the number of objects you create to return the result, there's an alternative with interface.
First you create an interfaceto be called whenever the limit is violated:
// A simple listener to be implemented by the calling method.
public interface OutOfLimitListener {
// Called whenever a limit is violated.
public void outOfLimit(int value, int maxValue);
// ... Add additional results as parameters
// ... Add additional states as methods
}
You can add parameters and/or methods. For example the actual position of the violating value could be a parameter. As antother example add a method that is called at the end of each test with parameters for the number of checks and the number of violates.
An implementation of this interface is passed as argument to your checking method. It calls the listener every time one of the limits is violated:
private boolean verifyLimits(Set<Integer> values, int maxValue, OutOfLimitListener listener) {
boolean result = true; // Assume all values are OK
for (Integer value : values) {
if (value > maxValue) {
listener.outOfLimit(value, maxValue);
result = false; // At least one was out of limits
}
}
return result;
}
And finally you use this method just by implementening the interface:
#Test
public final void test() throws IOException, InterruptedException {
// Make up a test set of random numbers
Set<Integer> testSet = new HashSet<Integer>();
for(int i=0; i<10; i++) testSet.add((int) (Math.random() * 100));
// Implement the interface once with appropriate reaction to an out-of-limit condition
OutOfLimitListener listener = new OutOfLimitListener() {
#Override
public void outOfLimit(int value, int maxValue) {
System.out.printf("The value %d exceeds the maximum value %d\n", value, maxValue);
}
};
// Call verification
verifyLimits(testSet, 50, listener);
}
Android and other GUI Interfaces use this pattern heavily. For me, it got the prefered method when the result contains more then one value.
Create your own custom unchecked exception that extends from RuntimeException.
You can use simple Key-Value, by using HashMap, of course with predefined keys.
Return the HashMap for further processing.
I would vote for the second solution (either using IllegalArgumentException or defining a specific one).
Generally good practice is ensuring that any return value from a method can safely be ignored (because some day somebody will forget to check it anyway) and, in cases when ignoring a return value is unsafe, it's always better to throw/catch an exception.
You could return the flag as a boolean and log the results of tests that don't verify, you'll want to log them anyhow...
presuming you'll be checking millions of values.