I wanted to know if there is any method to store if else condition in java? What I mean is like having a variable to represent the condition. This is my original code
private OnClickListener click2 = new OnClickListener() {
#Override
public void onClick(View v) {
tv1.setText("");
List<Integer> mClickedButtonIds = new ArrayList<Integer>();
int[] mDesiredOrder = new int[] { ans1.getId(), ans2.getId(), ans3.getId(),
ans4.getId(), ans5.getId() };
mClickedButtonIds.add(v.getId());
if (mClickedButtonIds.size() >= mDesiredOrder.length )
{
if (mClickedButtonIds.get(0) == mDesiredOrder[0]
&& mClickedButtonIds.get(1) == mDesiredOrder[1]
&& mClickedButtonIds.get(2) == mDesiredOrder[2]
&& mClickedButtonIds.get(3) == mDesiredOrder[3]
&& mClickedButtonIds.get(4) == mDesiredOrder[4]
)
{
tv1.setText("Correct!");
}
else
{
tv1.setText("Try Again!");
}
mClickedButtonIds.clear();
}
}
};
I plan to change it to something like this
private OnClickListener click2 = new OnClickListener() {
#Override
public void onClick(View v) {
tv1.setText("");
List<Integer> mClickedButtonIds = new ArrayList<Integer>();
int[] mDesiredOrder = new int[] { ans1.getId(), ans2.getId(), ans3.getId(),
ans4.getId(), ans5.getId(), ans6.getId() };
switch (main)
{
case 4 : Variable x = mClickedButtonIds.get(0) == mDesiredOrder[0]
&& mClickedButtonIds.get(1) == mDesiredOrder[1]
&& mClickedButtonIds.get(2) == mDesiredOrder[2]
&& mClickedButtonIds.get(3) == mDesiredOrder[3];
case 5 : Variable x = mClickedButtonIds.get(0) == mDesiredOrder[0]
&& mClickedButtonIds.get(1) == mDesiredOrder[1]
&& mClickedButtonIds.get(2) == mDesiredOrder[2]
&& mClickedButtonIds.get(3) == mDesiredOrder[3]
&& mClickedButtonIds.get(4) == mDesiredOrder[4];
case 6: Variable x = mClickedButtonIds.get(0) == mDesiredOrder[0]
&& mClickedButtonIds.get(1) == mDesiredOrder[1]
&& mClickedButtonIds.get(2) == mDesiredOrder[2]
&& mClickedButtonIds.get(3) == mDesiredOrder[3]
&& mClickedButtonIds.get(4) == mDesiredOrder[4]
&& mClickedButtonIds.get(5) == mDesiredOrder[5];
}
mClickedButtonIds.add(v.getId());
if (mClickedButtonIds.size() >= mDesiredOrder.length )
{
if (x)
{
tv1.setText("Correct!");
}
else
{
tv1.setText("Try Again!");
}
mClickedButtonIds.clear();
}
}
};
The Variable x is something which I would like to ask. Is there any method to do so or is there any variable that can store if else condition. Cause the original code, it is fixed to 5 clicks. Now I want the number of required clicks to change according to how many clicks the user want.
Based on the code snippet, consider a loop:
boolean result = true;
for (int i = 0; i < main; ++i) {
result = result && mClickedButtonIds.get(i) == mDesiredOrder[i];
if (!result)
break; // short-circuit out from loop if false
}
// now you can use "result" to test whether the condition matched all "main" ids
if (result) {
// correct
} else {
// bzzt, try again
}
If I understand correctly, that you want x to be a condition that you may change programatically (but which conforms to some structure) then you can do this using an interface Question and classes which implement that interface
public interface Question {
boolean getResponse(String condition1, int condition2);
}
public class StringIsLongCondition implements Question{
public boolean getResponse(String condition1, int condition2) {
return condition1.length()>condition2;
}
}
public class StringIsShortCondition implements Question{
public boolean getResponse(String condition1, int condition2) {
return condition1.length()<condition2;
}
}
Then use like
Question x;
//some code that selects the question
x= new StringIsShortCondition();
if(x.getResponse(someString, someInt){
//do something
}
Related
I have below code snippet, Is any other efficient way exists to achieve the same in java 8. I have tried lambda expression but throws error when i assign some variable inside lambda function.
public boolean countUsers(UserDetais details){
List<SystemProfile> systemProfileDataList = getSystemProfileData();
int userCountForService = service.getUserCountByService(details.id);
int vpcUsersCount=0;
int internetUsersCount=0;
if (systemProfileDataList != null) {
SystemProfile sysProfile;
Iterator profileItr = systemProfileDataList.iterator();
while (profileItr.hasNext()) {
SystemProfile sysProfile = (SystemProfile) profileItr.next();
if(sysProfile.getName().equalsIgnoreCase(IPConstants.DEFAULT_MAX_USERS)) {
vpcUsersCount = Integer.parseInt(sysProfile.getValue());
if (userCountForService > vpcUsersCount) {
maxUserFlag = true;
break;
}
}else if(sysProfile.getName().equalsIgnoreCase(IPConstants.DEAULT_MAX_USERS_WITH_INTERNET)) {
internetUsersCount = Integer.parseInt(sysProfile.getValue());
if (userCountForService > internetUsersCount) {
maxUserFlag = true;
break;
}
}
}
}
I think this should work :
boolean tooManyUsers = getSystemProfileData().stream()
.anyMatch((SystemProfile s) ->
s.getName().equalsIgnoreCase(IPConstants.DEFAULT_MAX_USERS)
&& Integer.parseInt(sysProfile.getValue()) < userCountForService
||
s.getName().equalsIgnoreCase(IPConstants.DEAULT_MAX_USERS_WITH_INTERNET)
&& Integer.parseInt(sysProfile.getValue()) < internetUsersCount
);
I am trying to rewrite and re-factor my code below but I do not have the same result at the end(List vgs does not contain the same result when I execute both function).
Also, I can not figure out what is wrong with my code below. Can someone tell me how can do to keep the order of my elements in List andVars, notVars and orVars?
The goal of this function is to remove all null or empty String element values of andVars & notVars list + all duplicate elements in my String element values of andVars & notVars list
for each varGroup element and keep the order of the elements of andVars, notVars list. Thank you
public static void RemoveDuplicateListElements(List<VarGroup> vgs) {
if (vgs == null) {
return;
}
for (VarGroup vg : vgs) {
RemoveDuplicateListElements(vg.getOrVars());
if (vg.getAndVars() != null) {
for (int x = vg.getAndVars().size()-1 ; x >= 0; x--) {
if (vg.getAndVars().get(x) == null
|| vg.getAndVars().get(x).isEmpty())
{
vg.getAndVars().remove(x);
} else {
for (int y = 0; y < x; y++) {
if (vg.getAndVars().get(x).equals(vg.getAndVars().get(y))) {
vg.getAndVars().remove(x);
break;
}
}
}
}
}
if (vg.getNotVars() != null) {
for (int x = vg.getNotVars().size()-1 ; x >= 0; x--) {
if (vg.getNotVars().get(x) == null
|| vg.getNotVars().get(x).isEmpty())
{
vg.getNotVars().remove(x);
} else {
for (int y = 0; y < x; y++) {
if (vg.getNotVars().get(x).equals(vg.getNotVars().get(y))) {
vg.getNotVars().remove(x);
break;
}
}
}
}
}
}
}
public class VarGroup {
private List<String> notVars = new ArrayList();
private List<VarGroup> orVars = new ArrayList();
private List<String> andVars = new ArrayList();
public List<VarGroup> getOrVs() {
return this.orVars;
}
public void setOrVars(List<VarGroup> orVars) {
this.orVars = orVars;
}
public List<String> getAndVars() {
return this.andVars;
}
public void setAndVars(List<String> andVars) {
this.andVars = andVars;
}
public List<String> getNotVars() {
return this.notVars;
}
public void setNotVars(List<String> notVars) {
this.notVars = notVars;
}
}
My refactoring is here:
public static void RemoveDuplicateListElements(List<VarGroup> vgs) {
if (vgs == null) {
return;
}
for (VarGroup vg : vgs) {
RemoveDuplicateListElements(vg.getOrVars());
if (vg.getAndVars() != null) {
vg.getAndVars().stream().distinct()
.filter(andVar -> Objects.nonNull(andVar) || !andVar.isEmpty())
.collect(Collectors.toList());
}
if (vg.getNotVars() != null) {
vg.getNotVars().stream().distinct()
.filter(notVar -> Objects.nonNull(notVar) || !notVar.isEmpty())
.collect(Collectors.toList());
}
}
}
I think you should extract some function here:
public static void removeDuplicateListElements(List<VarGroup> vgs) {
if (vgs == null) {
return;
}
for (final VarGroup vg : vgs) {
removeDuplicateListElements(vg.getOrVars());
handleVars(vg.getAndVars());
handleVars(vg.getNotVars());
}
}
private static void handleVars(final List<String> theVars) {
if (theVars != null) {
for (int x = theVars.size() - 1; x >= 0; x--) {
if (theVars.get(x) == null || theVars.get(x).isEmpty()) {
theVars.remove(x);
} else {
for (int y = 0; y < x; y++) {
if (theVars.get(x).equals(theVars.get(y))) {
theVars.remove(x);
break;
}
}
}
}
}
}
Method used (Intellij Idea):
select vg.getAndVars() and extract a variable for it
select vg.getOrVars() and extract a variable for it
got a warning about duplicated code
select the 1st bloc marked as duplicated and extract a method (accept IntelliJ proposal to replace 2nd block)
inline vars extracted in the 2 first steps
(Bonus step: some renaming)
This code in your refactored method does not do anything:
if (vg.getAndVars() != null) {
vg.getAndVars().stream().distinct()
.filter(andVar -> Objects.nonNull(andVar) || !andVar.isEmpty())
.collect(Collectors.toList());
}
It just creates a stream from the list, filters the stream, and then creates a new list from the filtered stream. But that new list is then immediately discarded. You should use the created filtered list using setAndVars, or e.g. using retainAll to modify the existing list.
Alternatively, if you want to use streams and lambdas, how about using removeIf? You can keep track of duplicates using a Set1). Simple example:
List<String> lst = new ArrayList<>(Arrays.asList("foo", "bar", "foo", "blub", null));
Set<String> seen = new HashSet<>();
lst.removeIf(x -> x == null || ! seen.add(x));
1) Usually you should not use methods with side effects in streams.
If you want duplicates removed and keeping order why don't you use a TreeSet
?
It looks to me like this code will remove every element of the list
for (int x = vg.getAndVars().size()-1 ; x >= 0; x--) {
// ...
for (int y = 0; y < x; y++) {
if (vg.getAndVars().get(x).equals(vg.getAndVars().get(y))) {
vg.getAndVars().remove(x);
break;
}
}
}
}
Since you're removing elements from the list in the loop, the data stored in a given index could change during the loop.
I am trying to create a win condition for my text game. I have two methods that decide whether a player has established criteria for a win or loss. These methods are in one class, while I want to use them in my controller class. The variables are hitTimes and nonHits:
class1:
if(choiceC > 0 || choiceR > 0)
{
Character currentCharacter;
currentCharacter= grid[choiceR][choiceC];
gameBoard[choiceR][choiceC] = currentCharacter;
loseTest(currentCharacter);
winTest(currentCharacter);
}
}
}
}
public int loseTest(Character currentCharacter)
{
int hitTimes = 0;
if(currentCharacter.minePresent == true)
{
hitTimes = 1;
}
return hitTimes;
}
public int winTest(Character currentCharacter)
{
int nonHits = 0;
if(currentCharacter.minePresent == false)
{
nonHits++;
}
return nonHits;
}
class2:
Grid grid = new Grid();
double notMines = grid.notMine;
View view = new View();
result = grid.toString();
view.display(result);
final int ITERATIONS = 13;
final int numGames = 1000;
for (int i=0;i <= numGames; i++)
{
while (hitTimes != 1 || nonHits != notMines )
{
grid.runGame();
result2 = grid.toString();
view.display(result2);
if(nonHits == ITERATIONS)
{
System.out.println("You Win!");
}
if(hitTimes == 1)
{
System.out.println("You Lose!");
}
}
}
You could make boolean attributes gameWon and gameLost, and put them both at false initial value. Then if conditions are fulfilled you turn one of them into true depending on the case of course. Make also getter methods in your class so you can access to them from another class.
Place this in your second method:
private boolean gameWon = false;
private boolean gameLost = false;
public boolean getGameWon() {
return gameWon;
}
public boolean getGameLost() {
return gameLost;
}
Change if condition to also have:
if(nonHits == ITERATIONS)
{
gameWon = true;
}
if(hitTimes == 1)
{
gameLost = true;
}
In your other class create this class and access your gameWon/gameLost values through getters.
SecondClass sc = new SecondClass();
boolean isGameWon = sc.gameWon();
boolean isGameLost = sc.gameLost();
Hopefully I gave you an idea.. I can't see your whole code so this is just an assumption I made of what's bothering you. Cheers!
I have the following code in a class "Shop":
public Item sellItem()
{
displayItems();
int indexID = Shop.getInput();
if (indexID <= -1 && indexID >= wares.length)
{
System.out.println("Null"); // For testing purposes
return null;
}
else
{
return wares[indexID];
}
}
And I'd like to know how to write an if statement checking if this method is returning null for my while loop in my main class:
int shopInput = scan.nextInt();
if(shopInput >= 1 && shopInput <= allShops.length)
{
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(???????? == null);
{
System.out.println("still null"); // For testing purposes
leaveShop = false;
}
}
}
Item item = allShops[shopInput - 1].sellItem();
if (item == null) {
System.out.println("still null"); // For testing purposes
...
}
(note that I removed the ; from the end of the if line)
Use this to check for null.
if (allShops[shopInput - 1].sellItem() == null) {}
EDIT: removed unnecessary double negative
I have several cases and I am just using simple if ... if else blocks.
How can I reduce the number of if statements in this code?
Perhaps I could use a lookup table, but I am not sure how to implement it in Java.
private int transition(char current, int state)
{
if(state == 0)
{
if(current == 'b')
{
return 1;
}
else
return 0;
}
if(state == 1)
{
if(current == 'a')
{
return 2;
}
else
return 0;
}
if(state == 2)
{
if(current == 's')
{
return 3;
}
else
return 0;
}
if(state == 3)
{
if(current == 'e')
{
return 3;
}
if(current == 'b')
{
return 4;
}
else
return 0;
}
if(state == 4)
{
if(current == 'a')
{
return 5;
}
else
return 0;
}
if(state == 5)
{
if(current == 'l')
{
return 6;
}
else
return 0;
}
else
return 0;
}
What you're trying to do looks very much like a finite state machine, and these are usually implemented with the help of a transition table. Once you set up the table, it's simply a matter of indexing to the position you want to get the return value. Assuming your return values are all less than 256, you can use a 2D byte array:
byte table[][] = new byte[NUM_STATES][NUM_CHARACTERS];
// Populate the non-zero entries of the table
table[0]['b'] = 1;
table[1]['a'] = 2;
// etc...
private int transition(char current, int state) {
return table[state][current];
}
Well, you can easily utilize hash. Simple and clean.
// declare hashtable
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("0-b", 1);
map.put("1-a", 2);
map.put("2-s", 3);
...
// get result
Integer result = map.get(state + "-" + current);
// change null (nothing found) to zero
return result == null ? 0 : result;
consider interfaces + enums:
interface State<T>
{
public void State<T> step(T input);
}
enum MyState implements State<Character> {
STATE0(0) { #Override public void MyState step(Character c) { return c == 'b' ? STATE1 : STATE0; }},
STATE1(1) { #Override public void MyState step(Character c) { return c == 'a' ? STATE2 : STATE0; }},
/* rest of states here */
final private int value;
MyState(int value) { this.value = value; }
public int getValue() { return this.value; }
}
class SomeClass
{
public MyState currentState = STATE0;
public void step(char input)
{
this.currentState = this.currentState.step(input);
}
}
i switch statement would be best here:
private int transition(char current, int state)
{
switch(state)
{
case 0:
return current == 'b' ? 1 : 0;
case 1:
return current == 'a' ? 2 : 0;
case 2:
return current == 's' ? 3 : 0;
case 3:
return current == 'e' ? 3 : (current == 'b' ? 4 : 0);
case 4:
return current == 'a' ? 5 : 0;
case 5:
return current == 'l' ? 6 : 0;
default:
return 0;
}
}
And a note, theres only 5 if statements there checking pure intergers, this is not exactly an overhead.
Looks like you need a better abstraction for a finite state machine. Think about a class that encapsulates what you want in a better way so you can extend it by configuration rather than modifying code.
If this code is about to be expanded over the time, why not use a state machine? Each state will return the next state based on the character it receives. Maybe it's an overkill for this code, but it'll be a lot easier to maintain, expand & read.
Use switch statement for the outer if chain:
switch (state) {
case 0: <code> ; break;
case 1: <code> ; break;
case 2: <code> ; break;
<etc>
default: return 0; break;
}