I need the currentStockLevel for another void Method in java, is there any possibility to get it?
I think no, because of void right?
public void receive (int currentStock)
{
String outLine;
if (currentStockLevel > 0)
outLine = productCode;
{
outLine = ". Current Stock: " + currentStockLevel;
outLine += " Current Stock changed from " + currentStockLevel;
currentStockLevel += currentStock;
outLine += " to " + currentStockLevel;
int storeCost = wholeSalePrice * currentStockLevel;
System.out.println (productCode + ":" + " Received " + currentStockLevel + "." + " Store Cost " + "$" + storeCost + "." + " New stock level: " + currentStockLevel);
}
Related
I am using the PDFBox to extract the character coordinates from the read PDF. However, I can't identify the unit of measurement of the value returned by the getXDirAdj () and getYDirAdj () methods?
#Override
protected void processTextPosition(TextPosition text) {
String tChar = text.getCharacter();
System.out.println("String[" + text.getXDirAdj() + ","
+ text.getYDirAdj() + " fs=" + text.getFontSize() + " xscale="
+ text.getXScale() + " height=" + text.getHeightDir() + " space="
+ text.getWidthOfSpace() + " width="
+ text.getWidthDirAdj() + "]" + text.getCharacter());
}
1 unit = 1/72 inch
"how to obtain the rotation of the character read": from the ExtractText.java tool:
static int getAngle(TextPosition text)
{
Matrix m = text.getTextMatrix().clone();
m.concatenate(text.getFont().getFontMatrix());
return (int) Math.round(Math.toDegrees(Math.atan2(m.getShearY(), m.getScaleY())));
}
I have a segment of code that splits a string into tokens and prints them each out on a new line. I am having a hard time writing a code that determines if a word is a reserved word or not. I have to print "Reserved word is: " if the word is a java keyword, otherwise print "Current word is: ". Here is my code so far:
package projectweek3;
/**
*
* Name -
* Email Address -
* Date -
*
*/
public class Week3Project {
final static String program = "/*\n" +
" * To change this license header, choose License Headers in Project Properties.\n" +
" * To change this template file, choose Tools | Templates\n" +
" * and open the template in the editor.\n" +
" */\n" +
"package testapplication2;\n" +
"\n" +
"import java.util.Scanner;\n" +
"\n" +
"/**\n" +
" *\n" +
" * #author james\n" +
" */\n" +
"public class TestApplication2 {\n" +
"\n" +
" /**\n" +
" * #param args the command line arguments\n" +
" */\n" +
" public static void main(String[] args) {\n" +
" Scanner input = new Scanner(System.in);\n" +
" \n" +
" System.out.println(\"Enter integer #1\");\n" +
" int num1 = input.nextInt();\n" +
" \n" +
" System.out.println(\"Enter integer #2\");\n" +
" int num2 = input.nextInt();\n" +
" \n" +
" System.out.println(\"Enter integer #3\");\n" +
" int num3 = input.nextInt();\n" +
" \n" +
" System.out.println(\"Enter integer #4\");\n" +
" int num4 = input.nextInt();\n" +
" \n" +
" System.out.println(\"Enter integer #5\");\n" +
" int num5 = input.nextInt();\n" +
" \n" +
" //determine the sum\n" +
" int sum = num1 + num2 + num3 + num4 + num5;\n" +
" \n" +
" //this is helpful to make sure your sum is correct\n" +
" System.out.println(\"The sum is: \" + sum);\n" +
" \n" +
" //why doesn't this generate the sum correctly\n" +
" double average = sum / 5;\n" +
" \n" +
" //The average, lets hope its right...\n" +
" System.out.println(\"The average of your numbers is: \" + average);\n" +
" \n" +
" }\n" +
" \n" +
"}\n" +
"";
**public static void main(String[] args)
{
String str = program;
String s = "";
for (int i = 0; i < str.length(); i++) {
s += str.charAt(i) + "";
if (str.charAt(i) == ' ' || str.charAt(i) == '\t' || str.charAt(i) == '\n' || (str.charAt(i) == ' ' && str.charAt(i) == '\n')) {
String currentWord = s.toString();
String res = "int";
if (currentWord.equals(res)) {
System.out.println("Reserved word is: [" + currentWord + "]");
}
else {
System.out.println("Current word is: [" + currentWord + "]");
}
s = "";//Clear the string to get it ready to build next token.
}
}**
I would reconsider the way you're looping through the "program."
Instead of going through character by character, use the Java String.split() function.
String program = "int num1 = input.nextInt();\n";
String[] words = program.split("[\\n\\s\\t]");
for (String word : words) {
System.out.println(word);
}
Output:
int
num1
=
input.nextInt();
EDIT:
Since you can't use String.split(), your looping solution looks good. To check if the current word is reserved, try using Set.contains().
Set<String> reserved = new HashSet<>();
reserved.add("int");
// ...
if reserved.contains(word) {
System.out.println("Reserved word is: " + word);
} else {
System.out.println("Current word is: " + word);
}
That is, assuming you're allowed to use Set.
I have a problem with a comparator. It works most of the time. I have created a test where it fails but I cannot see why it fails or what is wrong. It fails with the error of: java.lang.IllegalArgumentException: Comparison method violates its general contract!
The general situation is a list of fields from a PDF that are being sorted by page then by the Y position and then by the X position.
I hope someone can point me in the right direction as to why this is failing with the given test data.
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class DateUtilsTest extends TestCase {
public void testForDerrick() {
String fields = "null\t\t27.5118\t\t496.989\n" +
"null\t\t121.96\t\t192.52\n" +
"0\t\t79.5814\t\t301.597\n" +
"0\t\t79.5814\t\t264.662\n" +
"0\t\t196.29\t\t429.681\n" +
"0\t\t195.955\t\t314.32\n" +
"0\t\t196.868\t\t277.982\n" +
"0\t\t210.99\t\t429.681\n" +
"0\t\t210.82\t\t277.982\n" +
"0\t\t225.552\t\t429.681\n" +
"0\t\t224.029\t\t277.982\n" +
"0\t\t218.91\t\t198.61\n" +
"0\t\t267.12\t\t340.05\n" +
"0\t\t298.85\t\t346.5\n" +
"0\t\t372.16\t\t384.81\n" +
"null\t\t349.16\t\t346.5\n" +
"0\t\t549.35\t\t188.459\n" +
"0\t\t626.48\t\t457.041\n" +
"0\t\t649.28\t\t511.764\n" +
"0\t\t647.456\t\t503.618\n" +
"0\t\t647.456\t\t477.432\n" +
"0\t\t658.659\t\t539.6\n" +
"0\t\t658.659\t\t477.432\n" +
"0\t\t701.73\t\t474.041\n" +
"0\t\t712.98\t\t474.041\n" +
"0\t\t626.48\t\t121.0\n" +
"0\t\t626.48\t\t41.0\n" +
"0\t\t662.44\t\t117.0\n" +
"0\t\t673.611\t\t117.0\n" +
"0\t\t687.52\t\t117.0\n" +
"0\t\t700.73\t\t117.0\n" +
"0\t\t712.98\t\t117.0\n" +
"0\t\t787.169\t\t150.654\n" +
"null\t\t123.57\t\t532.77\n" +
"1\t\t35.6173\t\t92.42\n" +
"1\t\t47.83\t\t515.0\n" +
"1\t\t47.83\t\t369.25\n" +
"1\t\t76.5\t\t441.88\n" +
"1\t\t76.5\t\t368.85\n" +
"null\t\t123.57\t\t417.02\n" +
"1\t\t99.03\t\t515.0\n" +
"1\t\t99.03\t\t441.88\n" +
"1\t\t99.03\t\t369.25\n" +
"1\t\t99.03\t\t53.2\n" +
"1\t\t109.29\t\t515.0\n" +
"1\t\t109.29\t\t441.88\n" +
"1\t\t109.29\t\t369.25\n" +
"1\t\t109.29\t\t53.2\n" +
"1\t\t119.56\t\t515.0\n" +
"1\t\t119.56\t\t441.88\n" +
"1\t\t119.56\t\t369.25\n" +
"1\t\t119.56\t\t53.2\n" +
"1\t\t129.83\t\t515.0\n" +
"1\t\t129.83\t\t441.88\n" +
"1\t\t129.83\t\t369.25\n" +
"1\t\t129.83\t\t53.2\n" +
"1\t\t140.09\t\t515.0\n" +
"1\t\t140.09\t\t441.88\n" +
"1\t\t140.09\t\t369.25\n" +
"1\t\t140.09\t\t53.2\n" +
"1\t\t150.36\t\t515.0\n" +
"1\t\t150.36\t\t441.88\n" +
"1\t\t150.36\t\t369.25\n" +
"1\t\t150.36\t\t53.2\n" +
"1\t\t160.62\t\t515.0\n" +
"1\t\t160.62\t\t441.88\n" +
"1\t\t160.62\t\t369.25\n" +
"1\t\t160.62\t\t53.2\n" +
"1\t\t171.319\t\t515.0\n" +
"1\t\t171.319\t\t441.88\n" +
"1\t\t171.319\t\t369.25\n" +
"1\t\t171.319\t\t53.2\n" +
"1\t\t180.464\t\t401.15\n" +
"1\t\t192.194\t\t514.83\n" +
"1\t\t192.194\t\t441.71\n" +
"1\t\t192.194\t\t369.08\n" +
"1\t\t202.464\t\t514.83\n" +
"1\t\t202.464\t\t441.71\n" +
"1\t\t202.464\t\t369.08\n" +
"1\t\t202.464\t\t53.0295\n" +
"1\t\t212.724\t\t514.83\n" +
"1\t\t212.724\t\t441.71\n" +
"1\t\t212.724\t\t369.08\n" +
"1\t\t212.724\t\t53.0295\n" +
"1\t\t222.994\t\t514.83\n" +
"1\t\t222.994\t\t441.71\n" +
"1\t\t222.994\t\t369.08\n" +
"1\t\t222.994\t\t53.0295\n" +
"1\t\t233.254\t\t514.83\n" +
"1\t\t233.254\t\t441.71\n" +
"1\t\t233.254\t\t369.08\n" +
"1\t\t233.254\t\t53.0295\n" +
"1\t\t243.564\t\t514.83\n" +
"1\t\t243.564\t\t441.71\n" +
"1\t\t243.564\t\t369.08\n" +
"1\t\t243.564\t\t242.83\n" +
"1\t\t243.564\t\t136.83\n" +
"1\t\t253.874\t\t514.83\n" +
"1\t\t253.874\t\t441.71\n" +
"1\t\t253.874\t\t369.08\n" +
"1\t\t253.874\t\t242.83\n" +
"1\t\t253.874\t\t136.83\n" +
"1\t\t264.264\t\t514.83\n" +
"1\t\t264.264\t\t441.71\n" +
"1\t\t264.264\t\t369.08\n" +
"1\t\t264.264\t\t242.83\n" +
"1\t\t264.264\t\t136.83\n" +
"1\t\t274.154\t\t400.98\n" +
"1\t\t285.485\t\t515.0\n" +
"1\t\t285.485\t\t441.444\n" +
"1\t\t285.485\t\t369.25\n" +
"1\t\t285.485\t\t53.2\n" +
"1\t\t295.802\t\t515.0\n" +
"1\t\t295.802\t\t441.444\n" +
"1\t\t295.802\t\t369.25\n" +
"1\t\t295.802\t\t149.84\n" +
"1\t\t295.802\t\t104.36\n" +
"1\t\t305.576\t\t515.0\n" +
"1\t\t305.576\t\t441.444\n" +
"1\t\t305.576\t\t369.25\n" +
"1\t\t305.576\t\t242.29\n" +
"1\t\t305.576\t\t189.18\n" +
"1\t\t305.576\t\t107.88\n" +
"1\t\t316.153\t\t515.0\n" +
"1\t\t316.153\t\t441.444\n" +
"1\t\t316.153\t\t369.25\n" +
"1\t\t316.153\t\t198.06\n" +
"1\t\t316.153\t\t151.58\n" +
"1\t\t326.675\t\t515.0\n" +
"1\t\t326.675\t\t441.444\n" +
"1\t\t326.675\t\t369.25\n" +
"1\t\t326.675\t\t211.5\n" +
"1\t\t326.675\t\t165.02\n" +
"1\t\t336.47\t\t401.15\n" +
"1\t\t347.74\t\t515.0\n" +
"1\t\t347.74\t\t441.88\n" +
"1\t\t347.74\t\t369.25\n" +
"1\t\t347.74\t\t53.2\n" +
"1\t\t358.13\t\t515.0\n" +
"1\t\t358.13\t\t441.88\n" +
"1\t\t358.13\t\t369.25\n" +
"1\t\t358.13\t\t247.9\n" +
"1\t\t358.13\t\t153.0\n" +
"1\t\t368.02\t\t401.15\n" +
"1\t\t400.19\t\t442.787\n" +
"1\t\t400.19\t\t368.25\n" +
"null\t\t123.57\t\t306.57\n" +
"1\t\t423.977\t\t516.463\n" +
"1\t\t423.977\t\t443.343\n" +
"1\t\t423.977\t\t369.713\n" +
"1\t\t423.977\t\t54.6625\n" +
"1\t\t434.237\t\t516.463\n" +
"1\t\t434.237\t\t443.343\n" +
"1\t\t434.237\t\t369.713\n" +
"1\t\t434.237\t\t54.6625\n" +
"1\t\t444.507\t\t516.463\n" +
"1\t\t444.507\t\t443.343\n" +
"1\t\t444.507\t\t369.713\n" +
"1\t\t444.507\t\t54.6625\n" +
"1\t\t454.777\t\t516.463\n" +
"1\t\t454.777\t\t443.343\n" +
"1\t\t454.777\t\t369.713\n" +
"1\t\t454.777\t\t54.6625\n" +
"1\t\t465.037\t\t516.463\n" +
"1\t\t465.037\t\t443.343\n" +
"1\t\t465.037\t\t369.713\n" +
"1\t\t465.037\t\t54.6625\n" +
"1\t\t475.307\t\t516.463\n" +
"1\t\t475.307\t\t443.343\n" +
"1\t\t475.307\t\t369.713\n" +
"1\t\t475.307\t\t54.6625\n" +
"1\t\t485.567\t\t516.463\n" +
"1\t\t485.567\t\t443.343\n" +
"1\t\t485.567\t\t369.713\n" +
"1\t\t485.567\t\t54.6625\n" +
"1\t\t495.837\t\t516.463\n" +
"1\t\t495.957\t\t443.343\n" +
"1\t\t495.957\t\t369.713\n" +
"1\t\t495.957\t\t54.6625\n" +
"1\t\t506.847\t\t402.613\n" +
"1\t\t517.117\t\t516.463\n" +
"1\t\t517.117\t\t443.343\n" +
"1\t\t517.117\t\t369.713\n" +
"1\t\t517.117\t\t54.6625\n" +
"1\t\t527.387\t\t516.463\n" +
"1\t\t527.387\t\t443.343\n" +
"1\t\t527.387\t\t369.713\n" +
"1\t\t527.387\t\t54.6625\n" +
"1\t\t537.647\t\t516.463\n" +
"1\t\t537.647\t\t443.343\n" +
"1\t\t537.647\t\t369.713\n" +
"1\t\t537.647\t\t54.6625\n" +
"1\t\t547.917\t\t516.463\n" +
"1\t\t547.917\t\t443.343\n" +
"1\t\t547.917\t\t369.713\n" +
"1\t\t547.917\t\t54.6625\n" +
"1\t\t558.177\t\t516.463\n" +
"1\t\t558.177\t\t443.343\n" +
"1\t\t558.177\t\t369.713\n" +
"1\t\t558.177\t\t54.6625\n" +
"1\t\t568.447\t\t516.463\n" +
"1\t\t568.447\t\t443.343\n" +
"1\t\t568.447\t\t369.713\n" +
"1\t\t568.447\t\t54.6625\n" +
"1\t\t578.707\t\t516.463\n" +
"1\t\t578.707\t\t443.343\n" +
"1\t\t578.707\t\t369.713\n" +
"1\t\t578.707\t\t54.6625\n" +
"1\t\t588.977\t\t516.463\n" +
"1\t\t588.977\t\t443.343\n" +
"1\t\t588.977\t\t369.713\n" +
"1\t\t588.977\t\t54.6625\n" +
"1\t\t599.237\t\t516.463\n" +
"1\t\t599.237\t\t443.343\n" +
"1\t\t599.237\t\t369.713\n" +
"1\t\t599.237\t\t54.6625\n" +
"1\t\t609.507\t\t516.463\n" +
"1\t\t609.637\t\t443.343\n" +
"1\t\t609.637\t\t369.713\n" +
"1\t\t609.637\t\t54.6625\n" +
"1\t\t620.527\t\t402.613\n" +
"1\t\t630.787\t\t516.463\n" +
"1\t\t630.787\t\t443.343\n" +
"1\t\t630.787\t\t369.713\n" +
"1\t\t630.787\t\t54.6625\n" +
"1\t\t641.057\t\t516.463\n" +
"1\t\t641.057\t\t443.343\n" +
"1\t\t641.057\t\t369.713\n" +
"1\t\t641.057\t\t54.6625\n" +
"1\t\t651.317\t\t516.463\n" +
"1\t\t651.317\t\t443.343\n" +
"1\t\t651.317\t\t369.713\n" +
"1\t\t651.317\t\t54.6625\n" +
"1\t\t661.587\t\t516.463\n" +
"1\t\t661.587\t\t443.343\n" +
"1\t\t661.587\t\t369.713\n" +
"1\t\t661.587\t\t54.6625\n" +
"1\t\t671.847\t\t516.463\n" +
"1\t\t671.847\t\t443.343\n" +
"1\t\t671.847\t\t369.713\n" +
"1\t\t671.847\t\t54.6625\n" +
"1\t\t682.117\t\t516.463\n" +
"1\t\t682.117\t\t443.343\n" +
"1\t\t682.117\t\t369.713\n" +
"1\t\t682.117\t\t54.6625\n" +
"1\t\t692.387\t\t516.463\n" +
"1\t\t692.387\t\t443.343\n" +
"1\t\t692.387\t\t369.713\n" +
"1\t\t692.387\t\t54.6625\n" +
"1\t\t702.777\t\t516.463\n" +
"1\t\t702.777\t\t443.343\n" +
"1\t\t702.777\t\t369.713\n" +
"1\t\t702.777\t\t54.6625\n" +
"1\t\t712.667\t\t402.613\n" +
"2\t\t131.82\t\t494.835\n" +
"2\t\t166.95\t\t334.15\n" +
"2\t\t166.95\t\t311.9\n" +
"2\t\t180.85\t\t334.15\n" +
"2\t\t180.85\t\t311.9\n" +
"2\t\t193.091\t\t334.15\n" +
"2\t\t204.861\t\t334.15\n" +
"2\t\t198.31\t\t311.9\n" +
"2\t\t216.78\t\t334.15\n" +
"2\t\t216.78\t\t311.9\n" +
"2\t\t140.206\t\t286.44\n" +
"2\t\t140.206\t\t250.77\n" +
"null\t\t90.11\t\t192.52\n" +
"null\t\t47.83\t\t440.17\n" +
"null\t\t572.54\t\t197.55\n" +
"2\t\t140.206\t\t224.243\n" +
"2\t\t140.206\t\t188.434\n" +
"2\t\t152.411\t\t190.822\n" +
"2\t\t166.95\t\t191.0\n" +
"2\t\t198.31\t\t191.0\n" +
"2\t\t216.78\t\t191.0\n" +
"null\t\t166.95\t\t254.0\n" +
"2\t\t313.6\t\t501.8\n" +
"2\t\t313.6\t\t57.8\n" +
"2\t\t342.27\t\t501.8\n" +
"2\t\t342.27\t\t57.8\n" +
"2\t\t371.07\t\t501.8\n" +
"2\t\t371.07\t\t57.8\n" +
"2\t\t399.87\t\t501.8\n" +
"2\t\t399.87\t\t57.8\n" +
"2\t\t428.67\t\t501.8\n" +
"2\t\t428.67\t\t57.8\n" +
"2\t\t457.47\t\t501.8\n" +
"2\t\t457.47\t\t57.8\n" +
"2\t\t486.27\t\t501.8\n" +
"2\t\t486.27\t\t57.8\n" +
"2\t\t515.07\t\t501.8\n" +
"2\t\t515.07\t\t57.8\n" +
"2\t\t543.87\t\t501.8\n" +
"2\t\t543.87\t\t57.8\n" +
"2\t\t572.67\t\t501.8\n" +
"2\t\t572.67\t\t57.8\n" +
"2\t\t601.47\t\t501.8\n" +
"2\t\t601.47\t\t57.8\n" +
"2\t\t630.27\t\t501.8\n" +
"2\t\t630.27\t\t57.8\n" +
"2\t\t659.07\t\t501.8\n" +
"2\t\t659.07\t\t57.8\n" +
"2\t\t687.87\t\t501.8\n" +
"2\t\t687.87\t\t57.8\n" +
"2\t\t715.92\t\t501.8\n" +
"2\t\t715.92\t\t57.8\n" +
"3\t\t359.57\t\t394.05\n" +
"3\t\t390.22\t\t394.05\n" +
"3\t\t458.086\t\t545.206\n" +
"3\t\t458.086\t\t478.15\n" +
"3\t\t458.086\t\t317.306\n" +
"3\t\t488.85\t\t394.05\n" +
"3\t\t518.65\t\t394.05\n" +
"3\t\t538.809\t\t435.303\n" +
"3\t\t550.477\t\t435.303\n" +
"3\t\t568.55\t\t394.05\n" +
"3\t\t581.219\t\t436.03\n" +
"3\t\t590.989\t\t436.03\n" +
"3\t\t603.112\t\t436.03\n" +
"3\t\t620.3\t\t394.05\n" +
"3\t\t687.503\t\t317.306\n" +
"null\t\t639.63\t\t117.0\n" +
"null\t\t650.984\t\t117.0\n" +
"3\t\t314.184\t\t39.7711\n" +
"3\t\t336.086\t\t39.7711\n" +
"3\t\t358.272\t\t39.7711\n" +
"3\t\t571.296\t\t40.0028\n" +
"3\t\t599.766\t\t39.8304\n" +
"3\t\t621.736\t\t39.8304\n" +
"3\t\t665.499\t\t39.8304\n" +
"3\t\t687.859\t\t39.8304\n" +
"4\t\t115.997\t\t503.877\n" +
"4\t\t115.62\t\t324.0\n" +
"4\t\t115.62\t\t40.5\n" +
"4\t\t121.715\t\t215.873\n" +
"4\t\t188.51\t\t432.749\n" +
"4\t\t200.49\t\t432.75\n" +
"4\t\t220.99\t\t432.75\n" +
"4\t\t233.98\t\t432.75\n" +
"4\t\t244.96\t\t432.75\n" +
"4\t\t255.95\t\t432.75\n" +
"4\t\t266.94\t\t432.75\n" +
"4\t\t278.92\t\t432.75\n" +
"4\t\t288.55\t\t432.75\n" +
"4\t\t299.294\t\t432.749\n" +
"4\t\t312.88\t\t432.75\n" +
"4\t\t321.887\t\t432.75\n" +
"4\t\t188.51\t\t288.75\n" +
"4\t\t200.49\t\t288.75\n" +
"4\t\t220.99\t\t288.75\n" +
"4\t\t233.98\t\t288.75\n" +
"4\t\t244.96\t\t288.75\n" +
"4\t\t255.95\t\t288.75\n" ;
List<TestSort> testSortList = new ArrayList<TestSort>();
String[] fieldList = fields.split("\n");
for (String field : fieldList) {
String[] threeVals = field.split("\t\t");
TestSort df = new TestSort();
df.setPage(!"null".equals(threeVals[0]) ? Integer.valueOf(threeVals[0]) : null);
df.setTopLeftY(Double.valueOf(threeVals[1]));
df.setTopLeftX(Double.valueOf(threeVals[2]));
df.setFormField("");
testSortList.add(df);
}
Collections.sort(testSortList, new Comparator<TestSort>() {
#Override
public int compare(TestSort o1, TestSort o2) {
if (o1.getPage() == null || o2.getPage() == null || o1.getPage().equals(o2.getPage())) {
if (o1.getTopLeftY() == null || o2.getTopLeftY() == null || o1.getTopLeftY().equals(o2.getTopLeftY())) {
if (o1.getTopLeftX() == null || o2.getTopLeftX() == null || o1.getTopLeftX().equals(o2.getTopLeftX())) {
return o1.getFormField().compareTo(o2.getFormField());
} else {
return o1.getTopLeftX().compareTo(o2.getTopLeftX());
}
} else {
return o1.getTopLeftY().compareTo(o2.getTopLeftY());
}
} else {
return o1.getPage().compareTo(o2.getPage());
}
}
});
}
public class TestSort {
private Integer page;
private Double topLeftY;
private Double topLeftX;
private String formField;
public String getFormField() {
return formField;
}
public void setFormField(String formField) {
this.formField = formField;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Double getTopLeftY() {
return topLeftY;
}
public void setTopLeftY(Double topLeftY) {
this.topLeftY = topLeftY;
}
public Double getTopLeftX() {
return topLeftX;
}
public void setTopLeftX(Double topLeftX) {
this.topLeftX = topLeftX;
}
}
}
The exception is indicating that this is a non-transitive comparison. I have to agree with Dave Newton's comment that it's hard to reason about this comparator. All the null-checking is confusing, but it seems like the order that things get compared in is not consistent. See Effective Java, Item 12 (Consider Implementing Comparable):
If a class has multiple significant fields, the order in which you compare them is critical. You must start with the most significant field and work your way down. If a comparison results in anything other than zero (which represents equality), you’re done; just return the result. If the most significant fields are equal, go on to compare the next-most-significant fields, and so on. If all fields are equal, the objects are equal; return zero.
Specifically, if you're comparing a null field to a non-null field your code is trying to go on and compare the next most significant field, that means you're taking a case where one field is null and the other isn't, so one ought to sort higher than the other, and you're treating them as if they are equivalent, yet you're going forward with comparing the next most significant fields.
Here's a comparator written to comply with Bloch's advice, that tries to clean up the null-checking; nulls get replaced with a low-sorting value so the ordering will be consistent:
class TestSortComparator implements Comparator<TestSort> {
Double defaultIfNull(Double d) {
return d == null ? Double.NEGATIVE_INFINITY : d;
}
Integer defaultIfNull(Integer i) {
return i == null ? Integer.MIN_VALUE : i;
}
String defaultIfNull(String s) {
return s == null ? "" : s;
}
#Override
public int compare(TestSort o1, TestSort o2) {
int pageComp = defaultIfNull(o1.getPage())
.compareTo(defaultIfNull(o2.getPage()));
if (pageComp != 0) return pageComp;
int yComp = defaultIfNull(o1.getTopLeftY())
.compareTo(defaultIfNull(o2.getTopLeftY()));
if (yComp != 0) return yComp;
int xComp = defaultIfNull(o1.getTopLeftX())
.compareTo(defaultIfNull(o2.getTopLeftX()));
if (xComp != 0) return xComp;
return defaultIfNull(o1.getFormField())
.compareTo(defaultIfNull(o2.getFormField()));
}
}
Nathan's answer correctly summarizes the problem with your Comparator; it is not obeying the contract with regards to the transitivity of comparisons. From the Javadocs of compareTo():
The implementor must also ensure that the relation is transitive:
((compare(x, y) > 0) && (compare(y, z) > 0)) implies
compare(x, z) > 0
It can be difficult to write a null-safe comparator that compares multiple properties of an object -- even more difficult to write an implementation that's actually correct. Checking for nullness and keeping track of the value of the previous comparison makes the code clunky and verbose.
For the reasons mentioned above, it is preferable to utilize a proper framework to make the code more readable and less error-prone. Implementing a fluent Comparator is easy (and fun) with the help of Google Guava's ComparisonChain class. Here's how the Comparator looks like using ComparisonChain:
static class FluentComparator implements Comparator<TestSort> {
#Override
public int compare(TestSort o1, TestSort o2) {
return ComparisonChain
.start()
.compare(o1.getPage(), o2.getPage(),
Ordering.natural().nullsFirst())
.compare(o1.getTopLeftY(), o2.getTopLeftY())
.compare(o1.getTopLeftX(), o2.getTopLeftX())
.compare(o1.getFormField(), o2.getFormField())
.result();
}
}
Note how fluently you can chain the different comparisons into a "one-liner". Also, each comparison in the chain is lazily evaluated (i.e. only if required), making the implementation efficient without needing to write multiple return statements. From the docs:
ComparisonChain performs a "lazy" comparison: it only performs comparisons
until it finds a nonzero result, after which it ignores further input.
You need to be careful with nullable properties, however. As getPage() can return null in your example data, we need to use the overload of compare which accepts nullable inputs and a strategy for handling nulls (nulls first in this case).
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have read several posts suggesting to clear a JLabel (displayEntered) on a panel (display) with text by using the setText(" "). However, I have tried this and the outcome is it is just posting the array entered twice and does not clear the first set. I have an action shown below when a button is pressed both times; the first is to enter the data entered (I have the same code 4 times for the 4 different possible objects to enter but just put in the one since it's basically the same), which works fine and the second is to remove a specific one shown. My code is long, so am just putting that in. If someone wants something else please let me know. Thanks, I'd appreciate any input!
//adds the Herb data to the Array and list
enterHerbData.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals("Enter")){
Name = NameTxt.getText();
Colors = ColorTxt.getText();
ID = (int) IDCmbo.getSelectedItem();
Flavor = FlavorTxt.getText();
if(((String) MedicinalCmbo.getSelectedItem()).equals("Yes"))
Medicinal = true;
else
Medicinal = false;
if(((String) SeasonalCmbo.getSelectedItem()).equals("Yes"))
Seasonal = true;
else
Seasonal = false;
plants[count] = new Herb(Name, ID, Colors, Flavor, Medicinal, Seasonal);
String displayArraytemp = " ";
if(plants[count] != null){
if(plants[count] instanceof Flower){
displayArraytemp = ((count + 1) + ": " + plants[count].getID() + ", " + plants[count].getName() + ", " + ((Flower)plants[count]).getColor() + ", " + ((Flower)plants[count]).getSmell() + ", Thorny: " + ((Flower)plants[count]).getThorns() + "\n");
}
else if(plants[count] instanceof Fungus){
displayArraytemp = ((count + 1) + ": " + plants[count].getID() + ", " + plants[count].getName() + ", " + ((Fungus)plants[count]).getColor() + ", Poisonous: " + ((Fungus)plants[count]).getPoisonous() + "\n");
}
else if(plants[count] instanceof Weed){
displayArraytemp = ((count + 1) + ": " + plants[count].getID() + ", " + plants[count].getName() + ", " + ((Weed)plants[count]).getColor() + ", Edible: " + ((Weed)plants[count]).getEdible() + ", Medicinal: " + ((Weed)plants[count]).getMedicinal() + ", Poisonous: " + ((Weed)plants[count]).getPoisonous() + "\n");
}
else if(plants[count] instanceof Herb){
displayArraytemp = ((count + 1) + ": " + plants[count].getID() + ", " + plants[count].getName() + ", " + ((Herb)plants[count]).getColor() + ", " + ((Herb)plants[count]).getFlavor() + ", Medicinal: " + ((Herb)plants[count]).getMedicinal() + ", Poisonous: " + ((Herb)plants[count]).getSeasonal() + "\n");
}
sb.append("<html>" + displayArraytemp).
append("<br> ");
displayArray = sb.toString();
}
displayEntered.setText(displayArray);
count++;
frameB.setVisible(false);
}
}
});
//removes the data to the Array and panel
ActionListener RemoveAction = new ActionListener(){
#Override
public void actionPerformed(ActionEvent RemoveAction){
if(RemoveAction.getActionCommand().equals("Enter")){
if((Btn1).isSelected()){
String displayArraytemp2 = " ";
if(count >= 1){
for(int n = 0; n < count; n++){
plants[n] = plants[n+1];
}
count--;
frameB.setVisible(false);
displayEntered.setOpaque(true);
for(int n = 0; n < 25; n++){
if(plants[n] != null){
if(plants[n] instanceof Flower){
displayArraytemp2 = ((n + 1) + ": " + plants[n].getID() + ", " + plants[n].getName() + ", " + ((Flower)plants[n]).getColor() + ", " + ((Flower)plants[n]).getSmell() + ", Thorny: " + ((Flower)plants[n]).getThorns() + "\n");
}
else if(plants[n] instanceof Fungus){
displayArraytemp2 = ((n + 1) + ": " + plants[n].getID() + ", " + plants[n].getName() + ", " + ((Fungus)plants[n]).getColor() + ", Poisonous: " + ((Fungus)plants[n]).getPoisonous() + "\n");
}
else if(plants[n] instanceof Weed){
displayArraytemp2 = ((n + 1) + ": " + plants[n].getID() + ", " + plants[n].getName() + ", " + ((Weed)plants[n]).getColor() + ", Edible: " + ((Weed)plants[n]).getEdible() + ", Medicinal: " + ((Weed)plants[n]).getMedicinal() + ", Poisonous: " + ((Weed)plants[n]).getPoisonous() + "\n");
}
else if(plants[n] instanceof Herb){
displayArraytemp2 = ((n + 1) + ": " + plants[n].getID() + ", " + plants[n].getName() + ", " + ((Herb)plants[n]).getColor() + ", " + ((Herb)plants[n]).getFlavor() + ", Medicinal: " + ((Herb)plants[n]).getMedicinal() + ", Poisonous: " + ((Herb)plants[n]).getSeasonal() + "\n");
}
sb.append("<html>" + displayArraytemp2).
append("<br> ");
displayArray = sb.toString();
}
}
}
displayEntered.setText(" ");
displayEntered.setText(displayArray);
}
}
}};
Your real problem is that you are re-using sb without clearing it.
Basically, I have code that uses the same few lines in different scenarios, and it makes the code a bit messy (especially since I probably overcomplicated what I made, but that's another issue). What I wanted to do is store that piece of code as another function and calling it in the longer one. WHich should work as far as I know, except, the longer function has variables that aren't set in the shorter one, and if they were, I'm pretty sure it would change the final result of the function.
Here is the longer code:
public static void combat(Character a,Character b){
int battleturn = 1;
int maxTurns=20;
int draw1 = 0;
//stop after 20 turns, or stop when one player has 0 HP.
while (a.health > 0 && b.health > 0 && maxTurns > 0){
/* run a round of combat*/
if (b.health < 0.25 * b.maxHealth){
if (b.getFlee(a)){
System.out.println(">>>>>>>>>>The enemy has fled successfully<<<<<<<<<<");
break;
}else{
System.out.println("Battle turn " + battleturn + ", <attack> or <flee>?");
Scanner input = new
Scanner(System.in);
String move = input.next();
while(!move.equals("attack") && !move.equals("flee")){
System.out.println("Error: Please input <attack> or <flee>.");
input = new Scanner(System.in);
move = input.next();
}
if (move.equals("attack")){
System.out.println(a.name + " dealt " + a.combatRound(b) + " damage to " + b.name + "." + " Enemy has "
+ b.getHealth() + "/" + b.getMaxHealth() + " health.");
System.out.println(b.name + " dealt " + b.combatRound(a) + " damage to " + a.name + "." + " You have " +
a.getHealth() + "/" + a.getMaxHealth() + " health");
maxTurns--;
battleturn++;
}else if(move.equals("flee")){
if (a.getFlee(b)){
draw1++;
System.out.println(">>>>>>>>>>You have fled!<<<<<<<<<<");
break;
}else{
System.out.println(a.name + " dealt " + a.combatRound(b) + " damage to " + b.name + "." + " Enemy has " +
b.getHealth() + "/" + b.getMaxHealth() + " health.");
System.out.println(b.name + " dealt " + b.combatRound(a) + " damage to " + a.name + "." + " You have " +
a.getHealth() + "/" + a.getMaxHealth() + " health");
maxTurns--;
battleturn++;
}
}
}
}else{
System.out.println("Battle turn " + battleturn + ", <attack> or <flee>?");
Scanner input = new
Scanner(System.in);
String move = input.next();
while(!move.equals("attack") && !move.equals("flee")){
System.out.println("Error: Please input <attack> or <flee>.");
input = new Scanner(System.in);
move = input.next();
}
if (move.equals("attack")){
System.out.println(a.name + " dealt " + a.combatRound(b) + " damage to " + b.name+ "." + " Enemy has " +
b.getHealth() + "/" + b.getMaxHealth() + "health.");
System.out.println(b.name + " dealt " + b.combatRound(a) + " damage to " + a.name + "." + " You have " +
a.getHealth() + "/" + a.getMaxHealth() + " health");
maxTurns--;
battleturn++;
}else if(move.equals("flee")){
if (a.getFlee(b)){
draw1++;
System.out.println(">>>>>>>>>>You have fled!<<<<<<<<<<");
break;
}else{
System.out.println(a.name + " dealt " + a.combatRound(b) + " damage to " + b.name+ "." + " Enemy has " +
b.getHealth() + "/" + b.getMaxHealth() + " health.");
System.out.println(b.name + " dealt " + b.combatRound(a) + " damage to " + a.name + "." + " You have " +
a.getHealth() + "/" + a.getMaxHealth() + " health");
maxTurns--;
battleturn++;
}
}
}
}
}
As you can see there is a part of code that is repeated, and that is.
System.out.println("Battle turn " + battleturn + ", <attack> or <flee>?");
Scanner input = new
Scanner(System.in);
String move = input.next();
while(!move.equals("attack") && !move.equals("flee")){
System.out.println("Error: Please input <attack> or <flee>.");
input = new Scanner(System.in);
move = input.next();
}
if (move.equals("attack")){
System.out.println(a.name + " dealt " + a.combatRound(b) + " damage to " + b.name + "." + " Enemy has "
+ b.getHealth() + "/" + b.getMaxHealth() + " health.");
System.out.println(b.name + " dealt " + b.combatRound(a) + " damage to " + a.name + "." + " You have " +
a.getHealth() + "/" + a.getMaxHealth() + " health");
maxTurns--;
battleturn++;
}else if(move.equals("flee")){
if (a.getFlee(b)){
draw1++;
System.out.println(">>>>>>>>>>You have fled!<<<<<<<<<<");
break;
}else{
System.out.println(a.name + " dealt " + a.combatRound(b) + " damage to " + b.name + "." + " Enemy has " +
b.getHealth() + "/" + b.getMaxHealth() + " health.");
System.out.println(b.name + " dealt " + b.combatRound(a) + " damage to " + a.name + "." + " You have " +
a.getHealth() + "/" + a.getMaxHealth() + " health");
maxTurns--;
battleturn++;
}
}
}
It won't compile if I set that chunk of code as a method, because it doesn't have the variables battleturn, maxturns, draw1, but if I put them in there, the amount of battle turns messes up.
Any ideas?
Java applications should be modular: each class fulfilling its own function, each method generally performing a single operation.
In a method you can use either class variables or its own local variables.
If you need several methods work with the same data, it should either be part of a class (instance and/or static variables) or passed to each method as parameters.
Make sure that you do not define class variables in a method. This will create local variables that will shadow class variables.
This might help you accomplish what you're trying to do.
private static void reportDamage(Character a,
Character b) {
System.out.println(a.name + " dealt "
+ a.combatRound(b) + " damage to " + b.name
+ "." + " Enemy has " + b.getHealth() + "/"
+ b.getMaxHealth() + " health.");
}
I suggest changing your combat method like this.
int battleturn = 0;
int maxTurns = 20;
// stop after 20 turns, or stop when one player has 0
// HP.
Scanner input = new Scanner(System.in);
try {
while (a.health > 0 && b.health > 0
&& battleturn < maxturn) {
battleturn++;
/* run a round of combat */
if (b.getFlee(a)) {
System.out.println(">>>>>>>>>>"
+ "The enemy has fled successfully"
+ "<<<<<<<<<<");
break;
} else {
System.out.println("Battle turn "
+ battleturn + ", <attack> or <flee>?");
boolean isFlee = false;
boolean isAttack = false;
String move = input.next();
for (;;) {
isAttack = "attack".equalsIgnoreCase(move);
isFlee = "flee".equalsIgnoreCase(move);
if (isFlee || isAttack) {
break;
}
System.out.println("Error: "
+ "Please input <attack> or <flee>.");
move = input.next();
}
if (isAttack) {
reportDamage(a, b);
reportDamage(b, a);
} else { // isFlee
if (a.getFlee(b)) {
System.out.println(">>>>>>>>>>"
+ "You have fled successfully"
+ "<<<<<<<<<<");
break;
} else {
// b is fleeing.
// reportDamage(a, b);
reportDamage(b, a);
}
}
}
}
} finally {
input.close();
}