Code clean up for if else statement - java

Here is the peace of code, Which I am looking to make it more efficient
I see lots of if else statements,
Can any one help me to make it simple and reduce the number of lines of code
if(mmPageCounter.equalsIgnoreCase("trueNotFull")){
if(whatPageNext.equalsIgnoreCase("first"))
accountListSize = 5;
else
accountListSize = acctIdList.size();
}else if(mmPageCounter.equalsIgnoreCase("true")){
if(whatPageNext.equalsIgnoreCase("first"))
accountListSize = 5;
else
accountListSize = 10;
}else if(mmPageCounter.equalsIgnoreCase("false")){
if(whatPageNext.equalsIgnoreCase("alwaysFirst"))
accountListSize = acctIdList.size();
}
In the above code based on the mmPageCounter based on the value I am setting the
index of the For loop either to the full capactiy, or to the actual value
Full capacity means, The for loop will iterate only 10 items
ps : I have got the code working and its fine, But i am looking only for the fine tuning
If any one one has any fine tuning tips please share the links.

I would write it reversely.
When account size should be set to 10?
When account size should be set to 5?
if(shouldBeFive()){
accountListSize = 5;
} else if (shouldBeTen()){
accountListSize = 10;
} else{
accountListSize = acctIdList.size()
}
Also you can switch-case in java7.

This does not make it faster but reduces code, you can substitute:
if(whatPageNext.equalsIgnoreCase("first"))
accountListSize = 5;
else
accountListSize = 10;
by:
accountListSize = whatPageNext.equalsIgnoreCase("first") ? 5 : 10;
and:
if(whatPageNext.equalsIgnoreCase("first"))
accountListSize = 5;
else
accountListSize = acctIdList.size();
by:
accountListSize = whatPageNext.equalsIgnoreCase("first") ? 5 : acctIdList.size();
UPDATE:
If mmPageCounter can only be "trueNotNull", "true", or "false" then I think this code is equivalent:
int maxsize = mmPageCounter.equalsIgnoreCase("true") ? 10 : acctIdList.size();
if(mmPageCounter.equalsIgnoreCase("false")){
if(whatPageNext.equalsIgnoreCase("alwaysFirst"))
accountListSize = accountListSize = acctIdList.size();
} else {
accountListSize = whatPageNext.equalsIgnoreCase("first") ? 5 : maxsize
}
but you should write tests against current code and check that this code behaves exactly in the same way on edge cases.

My suggestion is not to make your code shorter, but more extensible and easier to maintain. It will however make the client code a lot shorter.
I would choose an enum but without a switch statement, as I can spot a strategy here and I'd prefer to encapsulate the logic outside the client. Also, I'd provide an abstraction (an interface) that would allow me or others to come with alternative implementations in the future, without adding new constants to the enum. The literal values for your strings and numbers I'd define as constants (in the abstraction, if that makes sense)
Here's the "strategy" abstraction:
interface PageCounter {
String FIRST = "first";
String ALWAYS_FIRST = "alwaysFirst";
int FIRST_SIZE = 5;
int DEFAULT_SIZE = 10;
int getAccountListSize(String whatPageNext, List<?> acctIdList);
}
Here's the enum implementing the PageCounter interface and providing the default implementations:
enum DefaultPageCounter implements PageCounter {
TRUENOTFULL {
#Override
public int getAccountListSize(String whatPageNext, List<?> acctIdList) {
return FIRST.equalsIgnoreCase(whatPageNext) ? FIRST_SIZE : acctIdList.size();
}
},
TRUE {
#Override
public int getAccountListSize(String whatPageNext, List<?> acctIdList) {
return FIRST.equalsIgnoreCase(whatPageNext) ? FIRST_SIZE : DEFAULT_SIZE;
}
},
FALSE {
#Override
public int getAccountListSize(String whatPageNext, List<?> acctIdList) {
// some default (non)value is required here: -1 can be whatever.
return ALWAYS_FIRST.equalsIgnoreCase(whatPageNext) ? acctIdList.size() : -1;
}
};
}
Here's your code (a lot shorter in the client, and unaware of the existing possibilities)
PageCounter counter = DefaultPageCounter.valueOf(mmPageCounter.toUpperCase());
int accountListSize = counter.getAccountListSize(whatPageNext, acctIdList);
The counter can be provided by some factory method so that you can switch the PageCounter implementation for subclasses (that's why I chose to use an interface after all), but I didn't want to make this more complicated than it already is.

If you know all possible values of mmPageCounter and whatPageNext beforehand, you can use a HashMap.
During initialization:
accountListSizes = new HashMap<String, Integer>();
accountListSizes.put("trueNotFull|first", 5);
accountListSizes.put("true|first", 5);
...
During computation:
String key = String.format("%s|%s", mmPageCounter, whatPageNext);
Integer value = accountListSizes.get(key);
if (value == null) {
accountListSize = acctIdList.size();
} else {
accountListSize = value;
}
This implementation is a little bit slower than yours, but it is much easier to read and extend. You can alter the mapping even at run-time.

Related

Foobar code working in IDE but not in Solution file

I've written code for a foobar challenge that works in my IDE but not in the solutions file provided by foobar. Also, is there anyway to show the output even if the test fails? Possibly to with it being a static method or the input being {1, 2, 3, 4} whereas mine is working with new int {1,2,3,4,5}? My code is:
public static int solution(int[] l) {
List<Integer> numberList = Arrays.stream(l).boxed().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
while (true) {
StringBuilder number = new StringBuilder();
int i = 0;
while (i < numberList.size()) {
number.append(numberList.get(i));
i++;
}
List<Integer> startingList = Arrays.stream(l).boxed().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
int testValue = numberList.size();
for (Integer integer : numberList) {
if (startingList.contains(integer)) {
startingList.remove(integer);
testValue--;
}
}
if (testValue == 0) {
int f = 0;
int total = 0;
while (f < numberList.size()) {
total = total + numberList.get(f);
f++;
}
if (total % 3 == 0) {
StringBuilder answer = new StringBuilder();
int c = 0;
while (c < numberList.size()) {
answer.append(numberList.get(c));
c++;
}
return Integer.parseInt(answer.toString());
}
}
Integer nextNumber = Integer.parseInt(number.toString()) - 1;
String[] stringArray = valueOf(nextNumber).split("");
numberList = new ArrayList<>();
for (String s : stringArray) {
numberList.add(Integer.parseInt(s));
}
}
}
Pretty rubbish but it does the job (at least in my IDE!)
As mentioned in a comment on the question, you should undoubtedly give some more context for your questions (since it is pretty unclear what your code is intended to do). I'm pretty sure I've inferred the actual question from context though, and I can suggest a couple of problems. In short (and a pretty good assumption for coding in general) the issue is not the environment running your code incorrectly, but rather your code having missed bugs due to lack of comprehensive testing. If you had presented a number of sample inputs and results I would guess you would have seen that your solution does not work locally.
The Java List.remove() method takes an index rather than a value to be removed (https://docs.oracle.com/javase/8/docs/api/java/util/List.html). The way it is used in your sample will result in throwing exceptions in a number of circumstances. Proper testing would have identified this (and will pick up most of your problems if fixed)
What happens if there is no solution? For example, an input of {1, 1} is going to get into a pretty messy state as the 'nextNumber' value slips below 0. You should know what the desired behavior is in this situation, and your tests should cover it before you try to upload a solution
This happened to me as well, but I then realized that my compilation was not successful because I have not imported the package that I am using at the top of the source code file like all java programs are write

Generate Unique Object ID

I'm trying to generate a new unique identifier for each object in a class, without using a static nextID field to just increment. Using that will create complications when unloading and unloading the program.
I came up with a solution to loop through the objects in a static method checking them all but for some unknown reason to me, it won't exit the while-loop.
I have been testing it in ideone.com here trying to create 5 objects to begin with, though it won't even create one.
Without having to go to the link to view the whole testing code, below is the method I'm using.
public static int newRandomID() {
int randomID = 0;
boolean notUnique = true;
while (notUnique) {
randomID = (int) (Math.random() * 999999 + 1);
for (Example e : examples) {
if (e.ID == randomID) {
notUnique = true;
break;
}
notUnique = false;
}
}
return randomID;
}
Have I just made a stupid mistake that I'm too blind to see, or is there a reason that this isn't working?
If all you need is a unique identifier (that need not be sequential) and it dosn't have to be an integer, have a look at java.util.UUID
your notUnique is bit confusing and i think you are doing it wrong in here
if (e.ID == randomID) {
notUnique = true;
break;
}
you dont need to break the statement if the id exists. i changed you code may be this helps.
int randomID = 0;
boolean ContinueLoop = true;
while (ContinueLoop) {
randomID = (int) (Math.random() * 999999 + 1);
boolean exist = false;
for (Example e : examples) {
if (e.ID == randomID) {
exist = true;
}else{
exist = false;
break;
}
}
if(exist==false){
ContinueLoop = false;
}else{
ContinueLoop = true;
}
}
return randomID;
Tried to execute your code (from the link you sent):
After you created and printed 50 new ids, I tried to generate 150,000 more:
for (int i = 0; i < 150000; i++)
new Example();
and... it works perfectly fine! Just took it a minute or so (which makes sense).
If I try to create only 15,000 records it works in less than a second.
Which leads me to the conclusion that miss rate is exponentially high and starts to be unbearable once you reach 15% of the ids capacity.
Don't continue with this solution.
Use a different approach such as a stored sequential number (if you store the records). If you don't store the records, I don't see a reason why not to use a static int variable.

issues with clone and for loop

private void buildDeck(ArrayList<Card> Monsters, ArrayList<Card> Spells) {
int monstersQouta = 15;
int spellsQouta = 5;
Random r = new Random();
for (; monstersQouta > 0; monstersQouta--) {
int randomIndex = r.nextInt(monsters.size());
MonsterCard monster = (MonsterCard) monsters.get(randomIndex);
MonsterCard clone = new MonsterCard(monster.getName(),
monster.getDescription(), monster.getLevel(),
monster.getAttackPoints(), monster.getDefensePoints());
clone.setMode(monster.getMode());
clone.setHidden(monster.isHidden());
clone.setLocation(Location.DECK);
deck.add(clone);
}
I need to know why we used here clone()
and how this for loop in this code works
As Andy Turner said for your first question :
clone() is not being used. It just so happens that the variable is called clone, but that has no semantic importance to the code.
Concerning the for statement he's composed of 3 parts ,each separated by one ; , and none of them is obligated to be there :
The first part is where you can, or not, declare your incremental variable : int i = 0;
The second part is where you must put an evaluation resulting on a boolean value : kappa.lengh >= i;
The thrid part is where you will modify the variable(s) values : i--;
Since none of these parts are obligated, you could write a correct for loop like this one : for(;;).
Here's a link to the documentation : For statement.

how to use if-else statement in accessor?

this is part of my program. I have to be sure that the amount of gas does not exceed the top gas capacity. I do not know how to write the else part? I ask the user to enter the current gas and it should be less or equal 30.
private final int GAS_CAP = 30
public int getGasCapacity(int gasCapacity)
{
if(currentGas <= GAS_CAP)
{
gasCapacity = GAS_CAP - currentGas;
}
else gasCapacity = currentGas;
return gasCapacity;
}
private final int GAS_CAP = 30
public int getGasCapacity()
{
int gasCapacity;
if(currentGas <= GAS_CAP)
{
gasCapacity = GAS_CAP - currentGas;
} else {
gasCapacity = 0;
}
return gasCapacity;
}
Your else statement was wrong, and there shouldn't be a parameter.
You could also easily accomplish this with one line, but I'm not sure if you know how to use ternary syntax.
Can made in one line as,
public int getGasCapacity(){
return (currentGas <= GAS_CAP ? (GAS_CAP - currentGas) : 0 );
}
First thing, you should make your question a little more clear because I don't really understand what you're trying to do. I'm going to write you what I think you're trying to achieve and you tell me if it's okay or comment what was wrong in the answer.
private final GAZ_LIMIT = 30;
public int ObserveGazCapacity(int gazCapacity)
{
if(gazCapacity<=GAZ_LIMIT)
{
gazCapacity-=GAZ_LIMIT;
}else{
gazCapacity=0; //in case higher than limit, capacity will be at the maximum value permitted
}
return gazCapacity;
}
Hopes that what you're looking for !

Is there a way to set a maximum size for a list?

I am looking for some help with the below problem. This is not my original code and I am quite new to Java, so I may be missing something obvious.
The code spawns some effects in a game I have, however there does not seem to be any upper limit on how many effects are spawned. Is there any way I can restrict the upper value of effects to some integer value? Say 20? Or can I make this value a random integer from say 20 to 30?
I have been trying to restrict the upper size of the list size but it doesn't seem to work.
Any suggestions appreciated.
I have also tried adjusting the value for(int j = 0; j < i; j++) to something like for(int j = 0; j < 20; j++), but this seems to have no effect either and the effects spawn as before.
I have also tried removing int i = list.size(); and Actor actor = (Actor)list.get(j); so that the code just relies on the for loop, but the code will not compile: it seems to require the code Actor actor = (Actor)list.get(j);. I get a cannot resolve symbol error for the following:
symbol : class pos
location: package actor
if(!flag && actor.pos.getAbsPoint().distance(point3d) < 10000D && (actor instanceof TypeBomber) && actor.getArmy() != myArmy)
symbol : variable actor
location: class com.maddox.il2.objects.vehicles.stationary.CandC$FireUnit
if(!flag && actor.pos.getAbsPoint().distance(point3d) < 10000D && (actor instanceof TypeBomber) && actor.getArmy() != myArmy)
symbol : variable actor
location: class com.maddox.il2.objects.vehicles.stationary.CandC$FireUnit
if(!flag && actor.pos.getAbsPoint().distance(point3d) < 10000D && (actor instanceof TypeBomber) && actor.getArmy() != myArmy)
public boolean danger()
{
boolean flag = false;
Point3d point3d = new Point3d();
pos.getAbs(point3d);
List list = Engine.targets();
World.MaxVisualDistance = 50000F;
int i = list.size();
for(int j = 0; j < i; j++)
{
Actor actor = (Actor)list.get(j);
if(!flag && actor.pos.getAbsPoint().distance(point3d) < 10000D && (actor instanceof TypeBomber) && actor.getArmy() != myArmy)
{
Random random = new Random();
int k = random.nextInt(500);
int l = k - 250;
k = random.nextInt(500);
int i1 = k - 250;
Eff3DActor.New(this, null, new Loc(l, i1, 0.0D, 0.0F, 90F, 0.0F), 1.0F, "Effects/Smokes/CityFire.eff", 600F);
flag = true;
int j1 = random.nextInt(10);
wait = (float)(1.0D + (double)j1 * 0.10000000000000001D);
}
}
Thanks for any help. Like I said, I'm sorry if I am missing something obvious.
I cannot say for sure what all of that code is doing, however, it appears that your function actually returns flag past the point that you pasted? It also appears that the size of the list of Actors is the upper bound of how many smoke effects can be made (limited by how many pass the if statement). That said I would try something like this (in order to preserve the rest of the function)
if(!flag && actor.pos.getAbsPoint().distance(point3d) < 10000D && (actor instanceof TypeBomber) && actor.getArmy() != myArmy)
{
if (renderedCount < 20)
{
Random random = new Random();
int k = random.nextInt(500);
int l = k - 250;
k = random.nextInt(500);
int i1 = k - 250;
Eff3DActor.New(this, null, new Loc(l, i1, 0.0D, 0.0F, 90F, 0.0F), 1.0F, "Effects/Smokes/CityFire.eff", 600F);
int j1 = random.nextInt(10);
wait = (float)(1.0D + (double)j1 * 0.10000000000000001D);
renderedCount += 1;
}
flag = true;
}
Make sure you declare int renderedCount before the for loop.
Now this should limit the function to creating 20 smoke effects each time it is called. Which brings us to the problems you are having where this kind of approach does not appear to work. Since you mentioned this is a game, I would be willing to bet that this function is called many times a minute (more than likely once per 'game tick'). If that is the case, limiting the number of smoke effects created by the function will not appear to do much of anything in the game. In order to limit the number completely you would have to do something a little more complex where you keep track of the number of smoke effects currently going globally. Which would probably involve keeping track of how much time has passed since the effect was started... (which it appears that wait might be the time the effect continues after it is started).
As for suggestions about how to keep track of things globally I might recommend a singleton and some methods on the singleton canCreate() and didCreate(float timeValue) then replace renderedCount < 20 with canCreate() and replace renderedCount += 1 with didCreate(wait).
Anyway, I hope this helps you some.
p.s. the complexity that goes with limiting this is a prime example of why ModelViewController is so important when designing something like this...
EDIT: rough singleton
public class SmokeCountSingleton {
private static SmokeCountSingleton instance = null;
private List<Long> smokeList = new ArrayList<Long>();
protected SmokeCountSingleton() {
}
public static SmokeCountSingleton getInstance() {
if(instance == null) {
instance = new SmokeCountSingleton();
}
return instance;
}
public boolean canCreate() {
cleanList()
return (smokeList.size() <= 20)
}
public void didCreate(float duration) {
//duration appears to be in seconds but we want it in milliseconds
smokeList.add(System.currentTimeMillis() + duration*1000)
}
private void cleanList(){
//remove items from list who have exceeded their duration
// have a value less than System.currentTimeMillis()
}
}
I do not have time to finish fleshing it out but hopefully that is enough to get you going.
The point of a singleton is that there is only ever one instance of it, it's kind of like having a database or some other external server that your program can use but without as much overhead. This way you don't ever have to declare it either, so you don't have to worry about where you would need to declare it, but it still acts as if you have a global list. To access the singleton instance (and the methods) you would just do:
SmokeCountSingleton.getInstance().canCreate()
SmokeCountSingleton.getInstance().didCreate(someDurationValue)
Like I said earlier, my Java is a little rusty, and I just mocked this up in the edit window; so apologies if it doesn't work 'out of the box'.
Also, as a side note, you may very well have multiple threads running that call functions where this would get accessed. So you may want to check out synchronized key word in Java...
use list.size() directly, instead of passing it to i. It will return number of objects the list is holding.
You can also use an Iterator or ListIterator to iterate through the list elements, as it will be easier, If you use these.
Example:-
Actor actor; //It would be better if you create variable here and use the same variable for different objects.
Iterator iter = list.iterator();
while(iter.hasNext()){
actor = (Actor)iter.next();
....//Rest of the code
}
I'll answer the question regarding whether we can set a maximum for a list. Hope that will help you to get to know Java better :)
Generally, an implementation of List does not have a maximum size, you can always add more element at the end of it.
In order to work around this would be to use a primitive array of Actor:
private static final int MAX_NUMBER_OF_ACTORS = 20
Actor[] actors = new Actor[MAX_NUMBER_OF_ACTORS];
That said, I would encourage you to use what the List interface has to offer to you, via its various implementations. Use, for example, an Arraylist and ovverride its add method:
public class ActorList extends ArrayList<Actor> {
private static final int MAX_NUMBER_OF_ACTORS = 20
#Override
public boolean add(Store s) {
boolean result = false;
if (this.size() <= MAX_NUMBER_OF_ACTORS){
result = super.add(s);
}else{
// Notify number maximum of actors have been reached (logging, whatever processing you want here...)
}
return result;
}
}
That would give you a nive control over the maximum size of your list of Actor instances.

Categories

Resources