I different values of a string variable viz { type1,type2,type3..}
I have different functions which are called on each string type and this logic is used at multiple places. What is the best way to code this?
Suppose you have a limited number of Strings. In that case you can implement the simple case of checking for each String and calling the appropriate function inside a wrapper function:
void function1(int a) {};
void function2(int a) {};
// ... etc
void callFunctionFromString(String s, int a)
{
if(s.contentEquals("string1"))
function1(a);
else if(s.contentEquals("string2"))
function2(a);
// .. etc
}
Every time you would have had a big if...else statement, just call callFunctionFromString() instead.
But let's assume that you have lots and lots of possible String values. In that case it is more efficient (when you call the function) to create a HashMap of String values to Method calls, like this:
interface methodInterface {
public void callFunction(int a);
}
void function1(int a) {};
void function2(int a) {};
// ... etc
public HashMap<String, methodInterface> stringToFunctionHash = new HashMap<String, methodInterface>();
void mapStringsToFunctions() throws NoSuchMethodException
{
stringToFunctionHash.put("string1", new methodInterface(){public void callFunction(int a){function1(a);}});
stringToFunctionHash.put("string2", new methodInterface(){public void callFunction(int a){function2(a);}});
// .. etc
}
void callFunctionFromString(String s, int a)
{
methodInterface m = stringToFunctionHash.get(s);
if(m != null)
m.callFunction(a);
}
Call mapStringsToFunctions() during your initialisation, and then call callFunctionFromString() as before.
If number od strings is big i advice you use "Chain of responsibility" pattern. This way calling code won't have to decide which function to call but every item in the chain will make decision if it should handle the request. Its also easy to add another handler to the chain.
Related
I Used Java HashSet for storing unique elements but now I want to retrieve element but HashSet does not has something like that, Here is what I want for my problem:
for my usecase LinkInfo hashCode() and equals() methods do not use LinkInfo.id field I want to get linkinfo instance from set and update all of its' fields except id field that should be from old instance
Set<LinkInfo> fooSet = new HashSet<>()
public void updateFoo(LinkInfo linkInfo) {
LinkInfo temp = fooSet.get(linkInfo);
linkInfo.setId(temp.getId());
// now update set
fooSet.remove(linkInfo)
fooSet.add(linkInfo)
}
Rather than
LinkInfo temp = fooSet.get(linkInfo);
the below logic is the same as what you seem to want
if (fooSet.contains(linkInfo)) {
temp = linkInfo;
}
I don't know why you're doing this, but to answer the question, yes you can do this, but you should use a map, like so:
import java.util.HashMap;
import java.util.Map;
public class Main {
static class Test {
public int a,b;
public Test(int a, int b) {
this.a = a;
this.b = b;
}
#Override
public boolean equals(Object obj) {
Test that = (Test)obj;
return this.a == that.a && this.b == that.b;
}
#Override
public int hashCode() {
return a ^ b;
}
}
public static void main(String[] args) {
Map<Test,Test> map = new HashMap<>();
Test t = new Test(1,2);
System.out.println(System.identityHashCode(t));
map.put(t, t);
Test t2 = new Test(1,2);
System.out.println(System.identityHashCode(t2));
System.out.println(System.identityHashCode(map.get(t2)));
}
}
Now you are able to retrieve the instance that you put into that map initially through an instance that is equal to it.
The program printed:
475266352
1355531311
475266352
on my computer. You can use a HashSet and iterate through it achieving the same result, but it won't be O(1).
You have a bit of a logical problem here. Why should an API that depends on equals() provide a method getElementEqualTo(e)? In order to use such a method, you need to present an object that, for the API's purposes, is equivalent to the desired result. What would be the point of that?
But that doesn't mean you're out of luck. I think you're saying that your LinkInfo class provides hashCode() and equals() methods suitable for identifying the object you want by means of a different object that you can obtain. In that case, it sounds like a HashMap could serve your purpose. Just map each key to itself.
HashMap<LinkInfo, LinkInfo> infos;
public void updateInfo(LinkInfo linkInfo) {
LinkInfo temp = infos.remove(linkInfo);
if (temp != null) {
linkInfo.setId(temp.getId());
}
infos.put(linkInfo, linkInfo);
}
I do agree with Scary answer above, but in case you want the exact reference that is stored in the Set instead of an similar equal object, you may use below code:
public void updateFoo(LinkInfo linkInfo) {
LinkInfo temp = null;
for(LinkInfo curLinkInfo:fooSet) if (curLinkInfo.equals(linkInfo))temp = curLinkInfo;
if(temp!=null)
linkInfo.setId(temp.getId());
// now update set
fooSet.remove(linkInfo)
fooSet.add(linkInfo)
}
It's part of a bigger program, but I'm stuck on this concept.
public static void mod (String a)
{
date.set(Calendar.a, 1 );
}
I want the method above to take in strings, so that it can work for DAY_OF_MONTH, YEAR, MONTH, etc etc. Like shown in main method below:
public static void main (String[] args)
{
mod("DAY_OF_MONTH");
mod("YEAR");
}
EDIT: There's missing initiations of "date" and etc but that's because I just took it from a bigger code. I'm stuck just on this concept.
The problem is that I can't even compile,
because there's an error with the " Calendar.a "
You can switch the String and code each section separately. From what you need to do the mod should look something like
public static void mod (String a)
{
switch(a){
case "DAY_OF_MONTH":
date.set(Calendar.DAY_OF_MONTH, 1 );
break;
/* and so forth for the other cases you want to handle */
}
The other possible solution is to write a function that would assign a String (in the same way) a static int with the flag required for set (i.e. "DAY_OF_MONTH" -> Calendar.DAY_OF_MONTH and so on)
A certain D'oh is in order :)
Your function should be
public static void mod(int a) {
date.set(a, 1); //Not sure where this date variable is from
}
public static void main(String[] args) {
mod(Calendar.DAY_OF_MONTH);
mod(Calendar.DAY_OF_WEEK);
}
If you look at the docs -> http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html
The fields are all integers so you can just refer to the field as Calendar.DAY_OF_WEEK and that passes as an int argument not a string.
You could also use a Map<String, Integer> to store the String value associated with the field.
Map<String, Integer> map = ....
map.put("DAY_OF_MONTH", Calendar.DAY_OF_MONTH);
and then do :
public static void mod (String a){
date.set(map.get(a), 1);
}
I am really tired of doing all the if null checks, resp. I also want to have a more configurable scenario for this. Let me explain this by an example:
I have a getter() which may return null or '0' in both cases the resp. setter() should not be called passing the getter().
So the implementation is
if(getter() != null && !getter().equals('0')) setter(getter());
this however really anoys me, especially if getter() and setter() are really long method calls and I have to introduce helper variables for this.
I am thinking about a method with parameter
ifNotSet(getter(), setter(), new Object[null, '0']);
which does exactly the same thing. Where the parameters to ifNotSet are
getter - the method to check if it does not equal one of the conditions
setter - the method to call in the way setter(getter) if conditions does not apply
conditions - the conditions which must not apply on evaluation of getter() for the method to be executed
At first sight this does not seem to complicated, it however is! Is anyone aware of a solution to this problem or any kind of implementation?
Thanks!
Update
I've been working some more on the problem, after the feedback of you guys, and found out about the following
private boolean ns(Object[] condition, Object getter) {
boolean ret = false;
for (Object object : condition) {
if(getter) equals or == ??
}
return true;
}
Object[] cond = new Object[] { null, "0" };
Object a;
if (ns(cond, a = getter()))setter(a);
Well, this seemed to be at least a solution if you have a lot of allocations to do. However, if you take a look at the ns() method... the question on the incoming conditions is, whether to use == or equals to do the comparison!?
You can use this way
public boolean checkNotNullOrZero(String s)
{
return (s!=null) && !s.equals("0");
}
Basic use:
if(checkNotNullOrZero(getter()))
{
setter(getter());
}
You can't do what that as in Java methods are not first-class citizens. You could use reflection or anon classes but it would be way more work .
If null and zero are always equivalent for getter then could that be changed to return just one of the two?
If null and zero are always equivalent for setter then could that be changed to normalize the two?
Could you create a method isNullOrZero(x) then you can have
if (!isNullOrZero(getter())) {
setter(getter());
}
Ugly way of doing this literally in Java:
public interface Getter {
public Object get();
}
public interface Caller {
public void call();
}
public void callIfNotNull(Getter getter, Caller caller, Object[] nullObjects) {
Object value = getter.get();
for(Object nullObject : nullObjects) {
if(value==nullObject) {
return;
}
}
caller.call();
}
Usage:
callIfNotNull(new Getter() {
#Override
public Object get() {
return getterMethod();
}
}, new Caller() {
#Override
public void call() {
setter();
}
}, new Object[]{null, '0'});
}
You might need to implement sane way to check for null objects and give reasonable names.
Personnaly, I wouldn't go with this approach. I would try to implement Null Object pattern to resolve an issue.
I want my custom functions to modify / toggle a boolean variable. Let's say that I have code like
if (OK2continue) { findANDclick(new String[]{"id", "menuButton"});}
if (OK2continue) { findANDclick(new String[]{"src", ".*homeicon_calendar.*"}); }
if (OK2continue) { findANDclick(new String[]{"src", ".*cycle_templates.*"});
I want to make sure that the flow of execution stops once any of the findANDclick functions toggles the variable OK2continue
I managed my functions to modify a String variable using StringBuilder.
Can I do the same for boolean type of variable?
I can't say it is equivalent. But using MutableBoolean offers you a mutable boolean wrapper, similar to the concept of StringBuilder a mutable sequence of characters. See this JavaDoc for details.
Push this code into its own method, and use a return:
if (findANDclick(new String[]{"id", "menuButton"})) return;
if (findANDclick(new String[]{"src", ".*homeicon_calendar.*"})) return;
if (findANDclick(new String[]{"src", ".*cycle_templates.*"})) return;
Given that all your method calls are the same, you could also use a loop:
String[][] buttons = {
{"id", "menuButton"},
{"src", ".*homeicon_calendar.*"},
{"src", ".*cycle_templates.*"},
};
for (String[] button: buttons) {
if (findANDclick(button)) return;
}
You might or might not find that more readable.
You need to clarify your reference to your usage of StringBuilder.
Assuming:
You pass reference of the StringBuilder to your method. String is changed in method. If this the case, then see #Gordon Murray Dent's answer.
Your boolean flag is visible in the method but is not passed. A simple Boolean will do.
package sof_6232851;
public class SideEffectingMethod {
static Boolean flag = false;
public static void main(String[] args) {
flag = true;
System.out.format ("flag is %b\n", flag);
clickMe();
System.out.format ("flag is %b\n", flag);
}
/** this method side-effects instance variable flag */
public static void clickMe () {
flag = !flag;
}
}
[edit list item #2 to reply to OP comment]:
Note that #2 is not really recommended. You mention your desire for "readable" code. Side-effecting methods works against that goal.
public class ReturnValuesForFunAndProfit {
public static void main(String[] args) {
presentUI();
}
public static void presentUI() {
if(!clickMe("woof")) return;
if(!clickMe("meow")) return;
if(!clickMe("hello")) return;
}
public static boolean clickMe (String blah) {
// your logic here; this ex. always returns true
return true;
}
}
Well, the concept of StringBuilder is to create a mutable and extendable String wrapper (meaning the string can be extended via append and the like :) ). You'd still have to pass it as a parameter to the method in order to modify it (or use a static var - not recommended).
Since boolean can't be extended, the only similarity would be the parameter to be mutable. So you can use MutableBoolean as Gordon suggested, but you'd still have to pass it.
Another option would be to return a boolean from findANDclick(...) and use the boolean opperators like: findAndClick(...) || findAndClick(...) || findAndClick(...) which would only execute the next findAndClick(...) if the previous returned false.
Since that option is somewhat hard to maintain, especially since you might have side effects in findAndClick(...) as well as being quite static and hard to read if you have more calls in there, you might want to use a list of function objects:
class FindAndClickExecutor {
public FindAndClickExecutor(String[] params) {...}
public boolean findAndClick() {...}
}
List<FindAndClickExecutor> faces = ...; //initialize appropriately
for( FindAndClickExecutor face : faces ) {
boolean ok2continue = face.findAndClick();
if( !ok2continue ) {
break;
}
}
Edit: since there seem to be other methods as well, you might use a more general list:
interface Executor {
boolean execute();
}
class FindAndClickExecutor implements Executor {
public boolean execute() {} // findAndClick code here, set parameters using constructor
}
class FindAndSelectOptionExecutor implements Executor {
public boolean execute() {} // findAndSelectOption code here
}
List<Executor> testCase1Sequence = ...; //initialize test case 1
List<Executor> testCase2Sequence = ...; //initialize test case 2
for( Executor ex : testCase1Sequence ) {
boolean ok2continue = ex.execute();
if( !ok2continue) {
break;
}
}
This example could also be expanded on, e.g. by using a more complex return value containing the continue flag and maybe more data (use interface here as well).
Edit 2: you could also use some scripting to define and the builder pattern to generate the list of executors for each test case.
public Solution getReferenceSolution(Problem p)
throws UnsupportedOperationException {
Solution result;
if (!haveReferenceSolution)
throw new UnsupportedOperationException("Domain.getReferenceSolution: A getReferenceSolution() method has not been specified for this domain. If its use is required, please specify one using setEquivalenceClasses() or by overriding Domain.getReferenceSolution().");
else {
if (haveBooleanSolutionCutoff)
result = findNearestEquivalenceClass(p).applyTo(p, booleanSolutionCutoff);
else
result = findNearestEquivalenceClass(p).applyTo(p);
}
result.setIsReferenceSolution(true);
return result;
}
If you only need one solution normally, but one place needs multiple solutions, I suggest you have two methods; something like this:
public Solution getReferenceSolution(Problem p)
{
// Code as before
}
public List<Solution> getAllSolutions(Problem p)
{
// Whatever you need to do here
}
Note how it's now obvious from the method name whether you're looking for one solution or multiple ones; I wouldn't use overloading in this situation, as you're trying to do different things.
Do you mean like this?
public Solution[] getReferenceSolution(Problem p) {
Solution result;
// set result.
return new Solution[] { result };
}
Maybe better to return a collection, e.g. an ArrayList:
public List<Solution> getReferenceSolution(Problem p)
throws UnsupportedOperationException {
List<Solution> solutions= new ArrayList<Solution>();
Solution result = ... // your code here
solutions.add(result);
return solutions;
}
Or maybe you want to pass the List as argument to the getReferenceSolution method and fill it inside the method?
public void getReferenceSolution(Problem p, List<Solution> solutions)
throws UnsupportedOperationException {
// your code to fill the list using solutions.add(Solution)
}