I'm fairly confident that there's no way this could work, but I wanted to ask anyway just in case I'm wrong:
I've heard many times that whenever you have a certain number of lines of very similar code in one batch, you should always loop through them.
So say I have something like the following.
setPos1(getCard1());
setPos2(getCard2());
setPos3(getCard3());
setPos4(getCard4());
setPos5(getCard5());
setPos6(getCard6());
setPos7(getCard7());
setPos8(getCard8());
setPos9(getCard9());
setPos10(getCard10());
setPos11(getCard11());
setPos12(getCard12());
There is no way to cut down on lines of code as, e.g., below, right?
for (i = 0; i < 12; i++) {
setPos + i(getCard + i)());
}
I'm sure this will have been asked before somewhere, but neither Google nor SO Search turned up with a negative proof.
Thanks for quickly confirming this!
No way to do that specifically in Java without reflection, and I don't think it would be worth it. This looks more like a cue that you should refactor your getcard function to take an integer argument. Then you could loop.
This is a simple snippet that shows how to loop through the getters of a certain object to check if the returned values are null, using reflection:
for (Method m : myObj.getClass().getMethods()) {
// The getter should start with "get"
// I ignore getClass() method because it never returns null
if (m.getName().startsWith("get") && !m.getName().equals("getClass")) {
// These getters have no arguments
if (m.invoke(myObj) == null) {
// Do something
}
}
}
Like the others stated, probably it's not an elegant implementation. It's just for the sake of completeness.
You could do it via reflection, but it would be cumbersome. A better approach might be to make generic setPos() and getCard() methods into which you could pass the index of the current item.
You need to ditch the getter/setter pairs, and use a List to store your objects rather then trying to stuff everything into one God object.
Here's a contrived example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Foo {
public static class Card {
int val;
public Card(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
public static class Position {
int value;
public Position(Card card) {
this.value = card.getVal();
}
}
public static void main(String[] args) {
List<Card> cards = new ArrayList<Card>(Arrays.asList(new Card(1), new Card(2), new Card(3)));
List<Position> positions = new ArrayList<Position>();
for (Card card : cards) {
positions.add(new Position(card));
}
}
}
You can't dynamically construct a method name and then invoke it (without reflection). Even with reflection it would be a bit brittle.
One option is to lump all those operations into one method like setAllPositions and just call that method.
Alternatively, you could have an array of positions, and then just loop over the array, setting the value at each index.
Card[] cardsAtPosition = new Card[12];
and then something like
public void setCardsAtEachPosition(Card[] valuesToSet) {
// check to make sure valuesToSet has the required number of cards
for (i = 0; i < cardsAtPosition.length; i++) {
cardsAtPosition[i] = valuesToSet[i];
}
}
Reflection would be your only option for your example case.
Related
I'm having a bit of trouble in my head trying to solve this:
I'm working on a "rankList", an arrayList made of "Score". Score it's the object that has the following atributes: name,wins,loses,draws. My class Ranking has an ArrayList of Score objects. To create a new Score object I just use the name (and set the rest to 0 since it's new). However I'm trying to check if the player's name it's already in rankList I don't have to create new but sum a win or lose or draw.
I have been reading arround that I have to override equals then others say I have to override contains... It's getting a big mess in my head. My fastest solution would be to write an "for" that goes arround the arrayList and use the getName().equals("name"); however this is getting too messi in my code. I have checkPlayer (if the palyer is in the list):
public boolean checkPlayer(String playerName) {
for (int i = 0; i < this.rankList.size(); i++) {
if (this.rankList.get(i).getName().equals(playerName)) {
return true;
}
}
return false;
}
then if I want to incrase the wins i have this :
public void incraseWins(String playerName) {
if (checkPlayer(playerName)) {
for (int i = 0; i < this.rankList.size(); i++) {
if (this.rankList.get(i).getName().equals(playerName)) {
this.rankList.get(i).setWins(this.rankList.get(i).getWins() + 1);
break;
}
}
} else {
createPlayer(playerName);
//more for to get to the player i'm looking for...
for (int i = 0; i < this.rankList.size(); i++) {
if (this.rankList.get(i).getName().equals(playerName)) {
this.rankList.get(i).setWins(this.rankList.get(i).getWins() + 1);
break;
}
}
}
So i guess there is a better way to do this... :/
ArrayList is not the right data structure here. To check if an element exists in the array you are searching the entire arraylist. Which means it's O(N).
To keep an array list is sorted order and do a binary search on it would definitely be faster as suggested in the comments. But that wouldn't solve all your problems either because insert into the middle would be slow. Please see this Q&A: When to use LinkedList over ArrayList?
One suggestion is to use a Map. You would then be storing player name, player object pairs. This would give you very quick look ups. Worst case is O(log N) i believe.
It's also worth mentioning that you would probably need to make a permanent record of these scores eventually. If so an indexed RDBMS would give you much better performance and make your code a lot simpler.
Try using a hashtable with a key, it would be much more efficient!
e..Why not using map<>.
a binary search is good idea if you must use List,code like this
List<Method> a= new ArrayList<>();
//some method data add...
int index = Collections.binarySearch(a, m);
Method f = a.get(index);
and class method is impl of Comparable,then override compareTo() method
public class Method implements Comparable<Method>{
........
#Override
public int compareTo(Method o) {
return this.methodName.compareTo(o.getMethodName());
}
if you don't want use binsearch,CollectionUtils in commons can help you
CollectionUtils.find(a, new Predicate() {
#Override
public boolean evaluate(Object object) {
return ((Method)object).getMethodName().equals("aaa");
}
});
in fact CollectionUtils.find is also a 'for'
for (Iterator iter = collection.iterator(); iter.hasNext();) {
Object item = iter.next();
if (predicate.evaluate(item)) {
return item;
}
}
So I wrote this function that behaves like Knuth's Algorithm X. Just for illustration - the function requires a large matrix of possible rows among which it tries to select the combination of the ones that make up for a legitimate solution.
The thing is, once we found the solution, since its void, the function doesn't return anything and instead just backtracks up (which consequently means it prints out sudoku for every level in the recursion depth).
Any suggestions on how to end the function the moment the solution is found? I am currently using System.exit(0) but that isn't nice since the program then ends the moment you find the solution (so anything you want to do afterwards is impossible - for example run the function on array of sudokus and solve each one).
The code is here:
public static void solve(ArrayList<int[]> solution, ArrayList<int[]> coverMatrix) {
if (Arrays.equals(solvedCase, workCase)) {
//this means we found the solution
drawSudoku(testOutput);
System.exit(0);
} else {
//find the column we didnt yet cover
int nextColToCover = findSMARTUnsatisfiedConstraint(coverMatrix, workCase);
//get all the rows that MIGHT solve this problem
ArrayList<int[]> rows = matchingRows(coverMatrix, nextColToCover);
//recusively try going down every one of them
for (int i = 0; i < rows.size(); i++) {
//we try this row as solution
solution.add(rows.get(i));
//we remove other rows that cover same columns (and create backups as well)
removeOtherRowsAndAdjustSolutionSet(coverMatrix);
if (isSolutionPossible(coverMatrix)) {
solve(solution, coverMatrix);
}
// here the backtracking occurs if algorithm can't proceed
// if we the solution exists, do not rebuild the data structure
if (!Arrays.equals(solvedCase, workCase)) {
restoreTheCoverMatrix(coverMatrix);
}
}
}
}
If I understand you correctly, you want to end recursion when you got the first solution. You can achieve this by having boolean return type for the method, and return true when you get first solution :.
public static boolean solve(ArrayList<int[]> solution, ArrayList<int[]> coverMatrix) {
if (Arrays.equals(solvedCase, workCase)) {
//this means we found the solution
drawSudoku(testOutput);
return true;
} else {
//find the column we didnt yet cover
int nextColToCover = findSMARTUnsatisfiedConstraint(coverMatrix, workCase);
//get all the rows that MIGHT solve this problem
ArrayList<int[]> rows = matchingRows(coverMatrix, nextColToCover);
//recusively try going down every one of them
for (int i = 0; i < rows.size(); i++) {
//we try this row as solution
solution.add(rows.get(i));
//we remove other rows that cover same columns (and create backups as well)
removeOtherRowsAndAdjustSolutionSet(coverMatrix);
if (isSolutionPossible(coverMatrix)) {
boolean result = solve(solution, coverMatrix);
if(result == true) return result;//else continue
}
// here the backtracking occurs if algorithm can't proceed
// if we the solution exists, do not rebuild the data structure
if (!Arrays.equals(solvedCase, workCase)) {
restoreTheCoverMatrix(coverMatrix);
}
}
return false;
}
}
You can use the AtomicReference Class with a Boolean:
public static void solve(ArrayList<int[]> solution, ArrayList<int[]> coverMatrix, AtomicReference<Boolean> test) {
if (Arrays.equals(solvedCase, workCase)) {
//this means we found the solution
drawSudoku(testOutput);
test.set(true);//System.exit(0);
}
solve(solution, coverMatrix, test);
if(!test.get())
{
// here the backtracking occurs if algorithm can't proceed
// if we the solution exists, do not rebuild the data structure
if (!Arrays.equals(solvedCase, workCase)) {
restoreTheCoverMatrix(coverMatrix);
}
}
You can call your method like this(just initialize the Boolean to false):
public static void main(String[] args)
{
AtomicReference<Boolean> test1 = new AtomicReference<Boolean>();
test1.set(false);
solve(***, ***, test1);
}
You could misuse the concept of exceptions for that, although I would not recommend it.
First define a custom exception class.
public class SuccessException extends Exception {}
Throw an instance on success.
if (Arrays.equals(solvedCase, workCase)) {
drawSudoku(testOutput);
throw new SuccessException();
}
Call the function initially in a try block.
try {
solve(solution, coverMatrix);
} catch(SuccessException e) {
/* Solution found! */
}
I'm trying to create a simple method which I have below:
public void analyzeWithAnalytics(String data) {
for (int i = 0; i < VALUE; i++) {
if (data.equals("action1")) {
// call a method on a value
}
if (data.equals("action2")) {
// call a different method on a value
}
}
This is only a small snippet (I took a lot out of my code), but essentially I want to be able to call a specific method without testing multiple lines in my for loop for which method to call.
Is there a way for me to decide what value to call by declaring a variable at the very beginning, instead of doing so many 'if statement' tests?
OK, I have an ArrayList inside my class:
private List<Value> values;
The value object has 2 fields time and speed.
Depending on the string I pass (time or speed), I want to be able to call the specific method for that field without doing multiple string comparisons on what method I passed.
For example, I want to be able to call getSpeed() or getTime() without doing a string comparison each time I want to call it.
I just want to test it once.
Another one:
enum Action {
SPEED {
public void doSomething() {
// code
}
},
TIME {
public void doSomething() {
// code
}
};
public abstract void doSomething();
}
public void analyzeWithAnalytics(Action data) {
for (int i = 0; i < VALUE; i++) {
data.doSomething();
}
}
You can have a Map which maps the names (action1, action2, ...) to classes which common parent and one method. And make call as following:
map.getClass("action1").executeMethod();
Map<String, MethodClass> theMap = new Map<>();
interface MethodClass {
executeMethod();
}
and children:
class MethodClass1 implements MethodClass{...}
class MethodClass2 implements MethodClass{...}
Your goal is not really clear from your question. Do you want to:
avoid typing the many cases?
gain code readability?
improve performance?
In case you're after performance, don't optimize prematurely! Meaning, don't assume that this will be important for performance without checking that out first (preferably by profiling). Instead focus on readability and perhaps laziness. ;)
Anyway, you can avoid the many tests inside by simply checking data outside of the loop. But than you'd have to copy/paste the loop code several times. Doesn't make the method more beautiful...
I would also recommend using case instead of if. It improves readability a lot and also gives you a little performance. Especially since your original code didn't use if - elseif - ... which means all conditions are checked even after the first was true.
Do I get this right? data will not be changed in the loop? Then do this:
public void analyzeWithAnalytics(String data) {
if (data.equals("action1")) {
for (int i = 0; i < VALUE; i++) {
// call a method on a value
}
} else if (data.equals("action2")) {
for (int i = 0; i < VALUE; i++) {
// call a different method on a value
}
}
}
You can also switch on strings (Java 7) if you don't like ìf...
You could try something like this, it would reduce the amount of typing for sure:
public void analyzeWithAnalytics(String data) {
for (int i = 0; i < VALUE; i++) {
switch(data) {
case "action1": doSomething(); break;
case "action2": doSomething(); break;
}
}
}
My professor gave me a code for the methods to be used in sorting an array of names lexicographically, but I have no idea how what to write inside the main class to show that the program works. I am very new to java, so please if you know how to do this could you write it as simple as possible for me to understand it. Thanks in advance.
This is are the classes
public class quicksort_class {
int[] array1 = new int[11];
public quicksort_class(int[] w)
{
array1 = w;
}
private static void sort(String[] string, int leftlimit, int rightlimit) {
if (rightlimit > leftlimit)
{
int midpoint = partitionstep(string, leftlimit, rightlimit);
sort(string, leftlimit, midpoint - 1);
sort(string, midpoint, rightlimit);
}
}
public static int partitionstep(String[] string, int leftlimit, int rightlimit)
{
String midpoint = string[rightlimit];
int lpointer = leftlimit;
int rpointer = rightlimit;
String temp = "";
while(string[lpointer].compareTo(midpoint) <= 0)
{
lpointer = lpointer ++;
}
while(string[rpointer].compareTo(midpoint) > 0)
{
rpointer = rpointer --;
}
if(lpointer > rpointer)
{
temp = string[lpointer];
string[lpointer] = string[rightlimit];
string[rpointer] = temp;
System.out.println(string);
}
while(lpointer < rpointer)
{
temp = string[lpointer];
string[lpointer] = string[rightlimit];
string[rightlimit] = temp;
}
return lpointer;
}
}
This is the main class (as you can see I have no idea what to write)
package quicksort;
public class Quicksort {
public static void main(String[] args) {
}
}
Write something that sets up an array of strings and calls sort against it, then prints out the results or checks them against a known good result.
Ideally, write something which does this repeatedly, with particular emphasis on checking unusual combinations (already sorted or sorted in reverse, null in the array, same value appearing several times or all values being identical...)
If you want to go beyond that, you need to dig into the code to understand its edge cases and specifically test those, and/or do a "code coverage" analysis (there are tools to help with that) to make sure all parts of the code have been exercised.
Assume the algorithm of sort method is correct:
1. If the main method is within the body of quicksort_class, you can directly call the sort method as sort(arrayToBeSorted, 0 , arrayToBeSorted.length-1). And the arrayToBeSorted should ordered lexicographically after your call. You can check that to confirm.
2. If the main method is in other class, as your main method currently, you need to at least change the private prefix of sort method to public, and call quicksort_class.sort(arrayToBeSorted, 0 , arrayToBeSorted.length-1).
Some tips:
1. Private prefix of method definition means this method can only be called inside current class body.
2. Static prefix of method definition means you should call this method via class name directly, instead of via a instance of class.
By the way, can you provide what the array1 attribute stands for? I don't get why it's there.
Sorry for the silly question, but I cannot seem to find an answer on google. I have written a class, and within the class there is a constructor which creates an arraylist, in the same class there is a method which iterates through the array list by creating an iterator object. As my code stands, however, it is not recognizing the arraylists name, should I store the array list in a class variable, or pass it into the method as an argument ?
What is usually best practice here as this is something that is always getting me ?
My code is as follows if you can't follow my somewhat convuluted explanation ! Apologies ! Thanks a lot for reading :)
import java.util.*;
public class Primes {
public Primes( int initialCapacity) {
ArrayList<Integer> listOfPrimeNumbers = new ArrayList<Integer>(initialCapacity);
//how do I get the above...
int index = 2;
while (index != listOfPrimeNumbers.size())
{
if (isPrime(index))
{
listOfPrimeNumbers.add(index);
}
index++;
}
}
public static boolean isPrime(int candidateNo) {
Iterator<Integer> iter = listOfPrimeNumbers.iterator( );
//in here ! ?
i=2;
while ( iter.hasNext( ) ) {
if (candidateNo%i==0 && i!=1) {
return false;
}
else
return true;
}
}
(Also, if you see anything horrifically wrong with my code please don't be afraid to call me out on it, the more constructive criticism the better!)
}
You define a private var for your ArrayList and initalize this variable in your Constructor.
Now you can access the list inside your Class :)
hope that helps.
import java.util.*;
public class Primes {
private ArrayList<Integer> listOfPrimeNumbers;
public Primes( int initialCapacity) {
listOfPrimeNumbers = new ArrayList<Integer>(initialCapacity);
//how do I get the above...
int index = 2;
while (index != listOfPrimeNumbers.size())
{
if (isPrime(index))
{
listOfPrimeNumbers.add(index);
}
index++;
}
}
public static boolean isPrime(int candidateNo) {
Iterator<Integer> iter = listOfPrimeNumbers.iterator( );
//in here ! ?
i=2;
while ( iter.hasNext( ) ) {
if (candidateNo%i==0 && i!=1) {
return false;
}
else
return true;
}
}
listOfPrimeNumbers is a local variable. You can either change it into a static member of the class, make it an instance variable and make isPrime non-static, or pass it as a parameter to isPrime.
Given the apparent intent of this class I'd make isPrime non-static and make listOfPrimeNumbers an instance variable.
You need to reconsider how your class is put together:
Having all the work done within the constructor is typically not a good idea. Constructors in Java are tricky, generally I try to make them as simple as possible, and have the real work go elsewhere.
Static methods are overrated, I try to avoid them. If you have some data structure you want your methods to access, make those methods instance methods and have the data structure be an instance variable. Java is supposed to be an object-oriented language, using static methods prevents object-orientation and restricts your options.
Think about how you want to use the class, and how you'd like to test it, and change the API implemented by the class to match that.
It seems you want to set the arraylist as a class member variable. However you're declaring isPrime as static. Those 2 things don't make sense together. If isPrime doesn't need to be static then simply store the arraylist as a class member. If it DOES need to be static (for whatever reason), you'll need to NOT have a constructor (because it wouldn't make sense with isPrime being static in this case) and create the arraylist somewhere else and pass it as an argument to isPrime.
Edit: on second thought, you don't need isPrime to be static, It should look like this:
public class Primes {
ArrayList<Integer> listOfPrimeNumbers;
public Primes( int initialCapacity) {
listOfPrimeNumbers = new ArrayList<Integer>(initialCapacity);
//how do I get the above...
int index = 2;
while (index != listOfPrimeNumbers.size())
{
if (isPrime(index))
{
listOfPrimeNumbers.add(index);
}
index++;
}
}
public static boolean isPrime(int candidateNo) {
Iterator<Integer> iter = listOfPrimeNumbers.iterator( );
//in here ! ?
i=2;
while ( iter.hasNext( ) ) {
if (candidateNo%i==0 && i!=1) {
return false;
}
else
return true;
}
}
However it seems like you have other problems. How will your while loop in your constructor ever end? You're incrempending index every time, but you're only adding something to your list if it's prime.
And in your isPrime method, what's the point of your while loop? You call iter.hasNext(), but don't use what its iterating over. You only ever check candidateNo and i.