how to write generics extensions for standart objects in java? - java

I beginner in Java and I ask tell me some words about Java tradition of writing generic code. I wrote helper class for pushing items into generic sorted collections in code below and I want to know it is accepted? Or I should extends some base class of collections? Or other ways to welcome more in Java?
package com.rkovalev.Helper;
import java.util.Comparator;
import java.util.List;
public abstract class ListExtensions {
public static <T> void addOnCompare(List<T> collection, T item, Comparator<T> comparator) {
synchronized(collection) {
int i = 0;
int size = collection.size();
if (size == 1) {
int diff = comparator.compare(item, collection.get(0));
switch(diff) {
case 1: i++; break;
default: break;
}
} else {
int range = size - 1;
i = size / 2;
int left = 0;
int right = range;
while(true) {
if (i <= 0) { i = 0; break; }
if (i > range) { i = range; break; }
int diff = comparator.compare(item, collection.get(i));
if (diff == 0) break;
else {
if (diff == -1) right = i;
if (diff == 1) left = i;
int near = i + diff;
if (near < 0) { i = 0; break; }
if (near > range) { i = range + 1; break; }
int diff_near = comparator.compare(item, collection.get(near));
if (diff_near == 0) { i = diff_near; break; }
if (diff_near == diff) {
int step = (right-left)/2;
if (step == 0) step = 1;
switch(diff){
case -1:
right = i;
i = i - step; break;
case 1:
left = i;
i = i + step; break;
}
} else if (diff > diff_near) {
i = near; break;
} else { break; }
}
}
}
collection.add(i, item);
}
}
}

If you want to make extra "generic" functionality available for all collection classes, then writing the functionality as a static method in a "helper" class is the right way to go.
Adding the method to a base class of the existing collection classes would not work. It would entail modifying the standard Java class library, and nobody in their right mind would do that. (It is technically possible, but you would be creating a portability nightmare for your code. Not to mention legal issues if you used the trademarked term "Java" in connection with your code.)

Related

How does OpenClover count branches?

The code:
public class Branches {
public double justOneIf(int a) {
double result;
if (a > 0) {
result = 1.0d;
} else {
result = -1.0d;
}
return result;
}
public String switches(int x) {
String result;
switch (x) {
case 0: {
result = "zero";
break;
}
case 1: {
result = "one";
break;
}
case 2: {
result = "two";
break;
}
default: {
result = "kill all humans";
}
}
return result;
}
public int deepIf(int x) {
int y;
if (x == 0) {
y = 1;
} else {
if (x > 0) {
y = 2;
} else {
y = 3;
}
}
return y;
}
}
In OpenClover (version 4.4.1) report I got metrics for this class:
Code metrics
Branches:6
...
Why six branches here? How does clover count it?
I've got it. It's pretty simple: one "IF" means 2 branches. Just it.
Branch coverage
Branch coverage (or 'decision coverage') is a code coverage metric
that measures which possible branches in flow control structures are
followed. Clover does this by recording if the boolean expression in
the control structure evaluated to both true and false during
execution.

Why is the method not acting "properly?"

I get the numbers scanned in correctly, but the methods aren't working right. First one doesn't do anything and the second one goes into an infinite loop.
Method called is not performing correctly. I am not sure what to do.
import java.util.Scanner;
public class testSequence {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a number: ");
int enterNumber = scan.nextInt();
System.out.println("1 for Iteration, 2 for Recursion: ");
int type = scan.nextInt();
if (type == 1){
computeIteration(enterNumber);
} else if (type == 2){
computeRecursion(enterNumber);
}
}
public static int computeIteration(int enterNumber) {
int answer;
int multiplier = 1;
int count = 0;
int addend = 0;
if (enterNumber == 0) {
count++;
return enterNumber;
} else if (enterNumber == 1) {
count++;
return enterNumber;
} else {
for (int i = 0; i <= enterNumber; i++) {//need to adjust "i" for counter correction
enterNumber = (multiplier * 2) + addend;
addend = multiplier;
multiplier = enterNumber;
count += 1;
}//end for loop
answer = enterNumber;
}//end else
return answer;
}//end computeIteration
public static int computeRecursion(int n) {
int count = 0;
if (n == 0) {
count++;
return 0;
} else if (n == 1) {
count++;
return 1;
} else {
count++;
return computeRecursion(2 * (n - 1)) + computeRecursion(n - 2);
}
}//end computerRecursion()
}//end Sequence()
You're never printing the answer.
if (type == 1){
computeIteration(enterNumber);
} else if (type == 2){
computeRecursion(enterNumber);
}
Note how you're calling the functions, but you never do anything with the result.
You probably meant:
if (type == 1){
System.out.println(computeIteration(enterNumber));
} else if (type == 2){
System.out.println(computeRecursion(enterNumber));
}
Or, if you wanted to get fancy:
UnaryOperator<Integer> f =
type == 1 ?
computeIteration
: computeRecursion;
System.out.println( f.apply(enterNumber) ) ;
Just an addition since you asked. I'm using the ternary operator because I need to choose between 2 things. In a case like this, it's neater than a full if statement.
The UnaryOperator is a functional interface. Basically, using them, you can save a function inside a variable. This is useful where in cases like this, you want to choose between 2 functions whose signatures are the same (both of your functions take an int, and give back an int), and use the result.
I save one of your functions into f, then call it by writing f.apply(9) (apply "applies" the arguments to the function; calling it).
Note you shouldn't use functional interfaces just for kicks, as they can make code less clear. When used properly though, they can make code much simpler; especially when paired with anonymous functions.

Array of Characters not updated properly java

I am trying to make pong in a terminal on windows in java.
I have an array of characters (called board) and the paddle positions are updated by the following code
public void movePaddles()
{
int inp = 0;
try
{
inp = System.in.read();
}
catch(Exception e)
{
return;
}
int olr = rtop;
int oll = ltop;
switch(inp)
{
case 'w':
ltop -=1;
break;
case 's':
ltop += 1;
break;
case 'i':
rtop -= 1;
break;
case 'k':
rtop += 1;
break;
}
updatePaddle('L',oll);
updatePaddle('R',olr);
}
public void updatePaddle(char side,int oldtop)
{
int edge = 0;
int top = 0;
// Leave 1 char of space
if (side == 'L')
{
edge = 1;
top = ltop;
}
else if (side == 'R')
{
edge = y-2;
top = rtop;
}
for (int i = oldtop;i < paddleSize+1;i++)
{
board[i][edge] = ' ';
}
for (int i = top;i < paddleSize+2;i++)
{
board[i][edge] = paddleChar;
}
}
What ends up happening is that the paddles disappear when moving down, making the game unplayable. What am I doing wrong?
(full code on github at https://github.com/Tookmund/Text-Pong)
I did try debugging my program before I posted my question but not properly it appears.
Basically I needed to add the value of the current location (top/oldtop) so that the loop would not exit prematurely because i was initially bigger that the paddleSize.

java.lang.reflect.InvocationTargetException error

I am working on a robot maze where the robot finds the target without bumping into walls. As a "backtrack" method, I need the robot to go in the opposite direction as it did when it first came across a junction. This is my code:
import uk.ac.warwick.dcs.maze.logic.IRobot;
import java.util.ArrayList;
import java.util.*;
import java.util.Iterator;
public class Explorer {
private int pollRun = 0; // Incremented after each pass.
private RobotData robotData; // Data store for junctions.
private ArrayList<Integer> nonWallDirections;
private ArrayList<Integer> passageDirections;
private ArrayList<Integer> beenbeforeDirections;
private Random random = new Random();
int [] directions = {IRobot.AHEAD, IRobot.LEFT, IRobot.RIGHT, IRobot.BEHIND};
public void controlRobot (IRobot robot) {
// On the first move of the first run of a new maze.
if ((robot.getRuns() == 0) && (pollRun ==0))
robotData = new RobotData();
pollRun++; /* Increment poll run so that the data is not reset
each time the robot moves. */
int exits = nonwallExits(robot);
int direction;
nonWallDirections = new ArrayList<Integer>();
passageDirections = new ArrayList<Integer>();
beenbeforeDirections = new ArrayList<Integer>();
// Adding each direction to the appropriate state ArrayList.
for(int item : directions) {
if(robot.look(item) != IRobot.WALL) {
nonWallDirections.add(item);
}
}
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
passageDirections.add(item);
}
}
for(int item : directions) {
if(robot.look(item) == IRobot.BEENBEFORE) {
beenbeforeDirections.add(item);
}
}
// Calling the appropriate method depending on the number of exits.
if (exits < 2) {
direction = deadEnd(robot);
} else if (exits == 2) {
direction = corridor(robot);
} else {
direction = junction(robot);
robotData.addJunction(robot);
robotData.printJunction(robot);
}
robot.face(direction);
}
/* The specification advised to have to seperate controls: Explorer and Backtrack
and a variable explorerMode to switch between them.
Instead, whenever needed I shall call this backtrack method.
If at a junction, the robot will head back the junction as to when it first approached it.
When at a deadend or corridor, it will follow the beenbefore squares until it
reaches an unexplored path. */
public int backtrack (IRobot robot) {
if (nonwallExits(robot) > 2) {
return robotData.reverseHeading(robot);
} else {
do {
return nonWallDirections.get(0);
} while (nonwallExits(robot) == 1);
}
}
// Deadend method makes the robot follow the only nonwall exit.
public int deadEnd (IRobot robot) {
return backtrack(robot);
}
/* Corridor method will make the robot follow the one and only passage.
The exception is at the start. Sometimes, the robot will start with
two passages available to it in which case it will choose one randomly.
If there is no passage, it will follow the beenbefore squares
until it reaches an unexplored path.*/
public int corridor (IRobot robot) {
if (passageExits(robot) == 1) {
return passageDirections.get(0);
} else if (passageExits(robot) == 2) {
int randomPassage = random.nextInt(passageDirections.size());
return passageDirections.get(randomPassage);
} else {
return backtrack(robot);
}
}
/* Junction method states if there is more than one passage, it will randomly select one.
This applies to crossroads as well as essentially they are the same.
If there is no passage, it will follow the beenbefore squares until it reaches an unexplored
path. */
public int junction(IRobot robot) {
if (passageExits(robot) == 1) {
return passageDirections.get(0);
} else if (passageExits(robot) > 1) {
int randomPassage = random.nextInt(passageDirections.size());
return passageDirections.get(randomPassage);
} else {
return backtrack(robot);
}
}
// Calculates number of exits.
private int nonwallExits (IRobot robot) {
int nonwallExits = 0;
for(int item : directions) {
if(robot.look(item) != IRobot.WALL) {
nonwallExits++;
}
}
return nonwallExits;
}
// Calculates number of passages.
private int passageExits (IRobot robot) {
int passageExits = 0;
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
passageExits++;
}
}
return passageExits;
}
// Calculates number of beenbefores.
private int beenbeforeExits (IRobot robot) {
int beenbeforeExits = 0;
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
beenbeforeExits++;
}
}
return beenbeforeExits;
}
// Resets Junction Counter in RobotData class.
public int reset() {
return robotData.resetJunctionCounter();
}
}
class RobotData {
/* It was advised in the specification to include the variable:
private static int maxJunctions = 10000;
However, as I am not using arrays, but ArrayLists, I do not
need this. */
private static int junctionCounter = 0;
private ArrayList<Junction> junctionList = new ArrayList<Junction>();
private Iterator<Junction> junctionIterator = junctionList.iterator();
// Resets the Junction counter.
public int resetJunctionCounter() {
return junctionCounter = 0;
}
// Adds the current junction to the list of arrays.
public void addJunction(IRobot robot) {
Junction newJunction = new Junction(robot.getLocation().x, robot.getLocation().y, robot.getHeading());
junctionList.add(newJunction);
junctionCounter++;
}
// Gets the junction counter for Junction info method in Junction class.
public int getJunctionCounter (IRobot robot) {
return junctionCounter;
}
// Prints Junction info.
public void printJunction(IRobot robot) {
String course = "";
switch (robot.getHeading()) {
case IRobot.NORTH:
course = "NORTH";
break;
case IRobot.EAST:
course = "EAST";
break;
case IRobot.SOUTH:
course = "SOUTH";
break;
case IRobot.WEST:
course = "WEST";
break;
}
System.out.println("Junction " + junctionCounter + " (x=" + robot.getLocation().x + ", y=" + robot.getLocation().y +") heading " + course);
}
/* Iterates through the junction arrayList to find the
heading of the robot when it first approached the junction. */
public int searchJunction(IRobot robot) {
Junction currentJunction = junctionIterator.next();
while (junctionIterator.hasNext()) {
if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y)))
break;
}
return currentJunction.arrived;
}
// Returns the reverse of the heading the robot had when first approaching the junction.
public int reverseHeading(IRobot robot) {
int firstHeading = searchJunction(robot);
int reverseHeading = 1; // Random integer to Iniitalise variable.
switch (firstHeading) {
case IRobot.NORTH:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.BEHIND;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.RIGHT;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.AHEAD;
else
reverseHeading = IRobot.LEFT;
break;
case IRobot.EAST:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.LEFT;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.BEHIND;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.RIGHT;
else
reverseHeading = IRobot.AHEAD;
break;
case IRobot.SOUTH:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.AHEAD;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.LEFT;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.BEHIND;
else
reverseHeading = IRobot.RIGHT;
break;
case IRobot.WEST:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.RIGHT;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.AHEAD;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.LEFT;
else
reverseHeading = IRobot.BEHIND;
break;
}
return reverseHeading;
}
}
class Junction {
int x;
int y;
int arrived;
public Junction(int xcoord, int ycoord, int course) {
x = xcoord;
y = ycoord;
arrived = course;
}
}
Whenever it is backtracking and reaches a junction it has already visited, it freezes and this comes up.
`java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor41.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at uk.ac.warwick.dcs.maze.controllers.PolledControllerWrapper.start(PolledControllerWrapper.java:70)
at uk.ac.warwick.dcs.maze.logic.ControllerThread.run(ControllerThread.java:46)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at RobotData.searchJunction(Explorer.java:242)
at RobotData.reverseHeading(Explorer.java:255)
at Explorer.backtrack(Explorer.java:74)
at Explorer.junction(Explorer.java:122)
at Explorer.controlRobot(Explorer.java:56)
... 5 more`
I don't think your searchJunction() is right or safe, the ConcurrentModificationException might be thrown due to the incorrect iterator through junctionList . The problem should be more about the iterator rather than reflection.
You might try:
private Iterator<Junction> junctionIterator = junctionList.iterator(); doesn't make much sense since the list is empty when initialize a RobotData object. Try to move it into searchJunction()
Check hasNext() first then invoke next()
public int searchJunction(IRobot robot) {
Iterator<Junction> junctionIterator = junctionList.iterator();
while (junctionIterator.hasNext()) {
Junction currentJunction = junctionIterator.next();
if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y)))
break;
}
return currentJunction.arrived;
}
It looks like that issue is in following code -
`public int searchJunction(IRobot robot) {
Junction currentJunction = junctionIterator.next();
while (junctionIterator.hasNext()) {
if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y)))
break;
}
return currentJunction.arrived;
}
You are calling junctionIterator.next() before calling junctionIterator.hasNext(). Iterator specification says that you should call next() only after calling hasNext()

Improve Java code: too many if's

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;
}

Categories

Resources