How to compare year month and day in java? - java

I'n my application i want to sort the "MyDate" class so, my teacher show me how to sort but how can i compare years first and then the rest?
Comparator<MyDate > dateCompare = new Comparator<MyDate >() {
#Override
public int compare(MyDate o1, MyDate o2) {
int dd1 = o1.getDateDay();
int mm1 = o1.getDateMonth();
//////years to compare ???????????????????
int years1 = o1.getYear();
int dd2 = o2.getDateDay();
int mm2 = o2.getDateMonth();
//////years to compare ?????????????????
int years2 = o2.getYear();
if (mm1 > mm2) {
return 1;
} else if (mm1 < mm2) {
return -1;
} else { // ==
if (dd1 > dd2) {
return 1;
} else if (dd1 < dd2) {
return -1;
} else {
return 0;
}
}
}
};
Collections.sort(list,dateCompare);

Compare the most significant field first. With a Date that is year.
Also, there is no need for a trailing else since the if and else if conditions return. Something like
if (years1 > years2) {
return 1;
} else if (years1 < years2) {
return -1;
}
if (mm1 > mm2) {
return 1;
} else if (mm1 < mm2) {
return -1;
}
if (dd1 > dd2) {
return 1;
} else if (dd1 < dd2) {
return -1;
}
return 0;

You could use the before() method of Date objects to compare the dates, it'll make writing code for your task very simple. Of course, that means that you have to convert your MyDate objects to Date but it should be very easy.

You can use the built-in functionality of the GregorianCalendar class to do this in a single line.
return new GregorianCalendar(years1, mm1 - 1, dd1).compareTo(new GregorianCalendar(years2, mm2 - 1, dd2));
Note that the - 1 in the month arguments are needed because the GregorianCalendar constructor uses a month value in the range of 0 to 11.

Related

Sorting an arrayList

I have to sort an arraylist by the date and time entered by the user but for some reason the output comes out not in order
Below this code it the code im using to order
public int compareTo(Vehicle v){
int returnValue = 0;
if (this.parkDate.year> v.parkDate.getYear() &&
this.parkDate.month> v.parkDate.getMonth() &&
this.parkDate.day> v.parkDate.getDay() &&
this.parkDate.hours> v.parkDate.getHours() &&
this.parkDate.minuets> v.parkDate.getMinuets()){
returnValue = 1; }
else
returnValue = - 1;
return returnValue;
}
Your comparison logic isn't correct. You might perform your comparisons with Integer.compare(int, int) and return the result in the case of non-zero. Something like,
public int compareTo(Vehicle v) {
int returnValue = Integer.compare(this.parkDate.getYear(),
v.parkDate.getYear());
if (returnValue != 0) {
return returnValue;
}
returnValue = Integer.compare(this.parkDate.getMonth(),
v.parkDate.getMonth());
if (returnValue != 0) {
return returnValue;
}
returnValue = Integer.compare(this.parkDate.getDay(),
v.parkDate.getDay());
if (returnValue != 0) {
return returnValue;
}
returnValue = Integer.compare(this.parkDate.getHours(),
v.parkDate.getHours());
if (returnValue != 0) {
return returnValue;
}
return Integer.compare(this.parkDate.getMinuets(),
v.parkDate.getMinuets());
}
Or, you could shorten the above by using arrays and something like
int[] a = { this.parkDate.getYear(), this.parkDate.getMonth(),
this.parkDate.getDay(), this.parkDate.getHours(),
this.parkDate.getMinuets() };
int[] b = { v.parkDate.getYear(), v.parkDate.getMonth(),
v.parkDate.getDay(), v.parkDate.getHours(),
v.parkDate.getMinuets() };
for (int i = 0; i < a.length; i++) {
int rv = Integer.compare(a[i], b[i]);
if (rv != 0) {
return rv;
}
}
return 0;
Finally, I believe you want minutes not minuets.
The primary issue is your comparison logic. You are testing that your vehicle's park date's year is greater than the other vehicle's park date's year and your vehicle's park date's month is greater than the other vehicle's park date's month and ditto for the day, hour and minute. This is incorrect.
Consider 2016-01-01 00:00 and 2015-12-31 23:59. The former clearly comes after the latter, but its month, day, hour and minute are all less than the other. Your logic would therefore fail to produce the correct result in this instance.
A more suitable approach would be to:
compare the years: if they are different you can return a result, ie. less than or greater than
if they are the same, compare the months; if they are different you can return a result
if they are the same, compare the days; if they are different you can return a result
if they are the same, compare the hours; if they are different you can return a result
if they are the same, compare the minutes; if they are different you can return a result
if they are the same, indicate the dates are equal
(Also, make sure you remembered to implement Comparable on your Vehicle class.)
The reason is because you have an error in your boolean logic.
if (this.parkDate.year> v.parkDate.getYear() &&
this.parkDate.month> v.parkDate.getMonth() &&
this.parkDate.day> v.parkDate.getDay() &&
this.parkDate.hours> v.parkDate.getHours() &&
this.parkDate.minuets> v.parkDate.getMinuets()){
returnValue = 1; }
else
returnValue = - 1;
Else is like taking the negation of your if statement. In this case that equates to the following:
this.parkDate.year <= v.parkDate.getYear()
OR
this.parkDate.month <= v.parkDate.getMonth()
OR
this.parkDate.day> v.parkDate.getDay()
...
In other words
Negation(A && B) <=> (Negation(A) || Negation(B))
In the context of your situation, your else logic could be true even if the year is greater than this.parkDate
I think this should be enough to help you get it right. :)
i think you can use "compareTo" the result is 0, 1, -1
public int compareTo(Vehicle a, Vehicle b){
return a.parkDate.compareTo(b.parkDate);
}
Instead of storing the date and time as primitives, you can create a LocalDateTime and use it in Comparator
add field parkDate as LocalDateTime in Vehicle class
LocalDateTime parkDate = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second);
use the parkDate in compareTo method
#Override
public int compareTo(Vehicle o) {
return this.parkDate.compareTo(o.parkDate);
}

How to compare to BigInts in Java to determine which one is the larger BigInt

I'm trying to compare two BigInts that were manually created and did not use the built-in BigInt class. Right now I'm getting hung up trying to be able to determine how to find the bigger number of the 2. For example if I want to find which number is bigger between 123 and 134, and I pass in both BigInts I want to return a false if 123 is the first number passed or True if the second number is passed. Please see the code below:
private boolean thisBigIntGreaterThanOrEqualToOther(BigInt b1, BigInt b2){
boolean value = true;
if(b1.bigInt.size() >= b2.bigInt.size()){
for(int i = 0; i < b2.bigInt.size(); i++){
if(b1.bigInt.get(i) >= b2.bigInt.get(i)){
value = true;
}
else{
value = false;
}
}
}
else{
value = false;
}
return value;
}
As you can see in my code I thought about trying to compare each digit, but I run into an issue when I get to 1's for each number, it sets the value to true.
BigInt Class Below:
public class BigInt {
//Instance variables for the class, a boolean for the sign and an ArrayList to store the input String
private boolean pos = true;
private ArrayList<Integer> bigInt = new ArrayList<Integer>();
//No argument constructor, creates a big integer of value zero
public BigInt () {
this.pos = true;
}
//Constructor for big integers input as int
public BigInt (int newBigInt) {
String inputInt = Integer.toString(newBigInt);
inputInt = handleSign(inputInt);
inputInt = checkNumber(inputInt);
for(int i = inputInt.length() - 1; i >=0; i--) {
bigInt.add(Integer.parseInt(inputInt.substring(i, i+1)));
}
}
//Constructor for big integers input as strings
public BigInt (String newBigInt) {
newBigInt = handleSign(newBigInt);
newBigInt = checkNumber(newBigInt);
for(int i = newBigInt.length() - 1; i >=0; i--) {
bigInt.add(Integer.parseInt(newBigInt.substring(i, i+1)));
}
}
private String handleSign(String num) {
if(num.charAt(0) == '+' || num.charAt(0) == '-') {
if(num.length() == 1) {
throw new ErrorMessage("Invalid value: sign only, no integer.");
}
if(num.charAt(0) == '-') {
this.pos = false;
}
else {
this.pos = true;
}
num = num.substring(1);
}
return num;
}
// Private method to remove leading zeros from add/subtract methods
private BigInt removeZeros(BigInt result){
for(int i = 0; i < result.bigInt.size(); i++){
if(result.bigInt.get(i) == 0){
result.bigInt.remove(i);
}
}
return result;
}
//Private method to check the number; remove leading zeros and check for leading spaces (throw error message)
private String checkNumber(String num) {
if(num.charAt(0) == ' ') {
throw new ErrorMessage("Invalid value: leading blank space.");
}
if(num.charAt(0) == '0'){
while(num.length() > 1 && num.charAt(0) == '0') {
num = num.substring(1);
}
}
return num;
}
//toString method
public String toString() {
String answer = "";
for(int i = bigInt.size() - 1; i >=0; i--) {
answer = answer + bigInt.get(i);
}
if(this.pos == false){
return "-" + answer;
}
return answer;
The method to compare two BigInts is broken in several ways:
1. You iterate in the wrong direction:
for(int i = 0; i < b2.bigInt.size(); i++)
You start from the least significant digit which means 20 would be considered smaller than 11. Change it to
for(int i = b2.bigInt.size() - 1; i >= 0 ; i--)
2. You override the result of the comparison
If your code reaches the point where it sets value = false; it does not return or exit the loop. That means that in the next iteration the value gets overriden. That means suddenly 13 and 23 are considered equal.
BigInt c = new BigInt("13");
BigInt d = new BigInt("23");
System.out.println(BigInt.thisBigIntGreaterThanOrEqualToOther(c, d));
System.out.println(BigInt.thisBigIntGreaterThanOrEqualToOther(d, c));
The output is
true
true
Change value = false; to return false;
3. You do not check whether b1.bigInt.size() > b2.bigInt.size()
This results in your method returning that 131 is smaller than 23.
Change your code in the following way:
if(b1.bigInt.size() > b2.bigInt.size()){
return true;
} else if(b1.bigInt.size() < b2.bigInt.size()){
return false;
} else {
// the other comparison code
}
Some final remarks:
It is good design to implement the Comparable interface as it allows you to use many library methods with your class.
EDIT: code now does not use library functions anymore
public class BigInt implements Comparable<BigInt> {
...
#Override
public int compareTo(BigInt other) {
int c = this.bigInt.size() - other.bigInt.size();
if (c != 0) {
return c;
} else {
for (int i = this.bigInt.size() - 1; i >= 0; i--) {
c = this.bigInt.get(i) - other.bigInt.get(i);
if (c != 0) {
return c;
}
}
return 0;
}
}
}

Recursive method checking whether a row of integers is descending: return true/false

I have to write a recursive method in Java that returns true if a row is descending and false it does not.
This is what I tried, but it doesn't work properly:
ArrayList<Integer> getallen = new ArrayList();
getallen.add(500);
getallen.add(400);
getallen.add(300);
getallen.add(200);
getallen.add(100);
getallen.add(0);
System.out.println(isDescending(getallen));
}
public static boolean isDescending(ArrayList<Integer> getallen) {
if (getallen.size() >= 2) {
if (getallen.get(0) < getallen.get(1)) {
return false;
} else if (getallen.size() > 0) {
getallen.remove(0);
return isDescending(getallen);
} else {
return true;
}
} else {
return false;
}
}
I think you have unnecessary cases if the size is less than 2 you can only assume true.
Try:
public static boolean isDescending(ArrayList<Integer> getallen) {
if (getallen.size() >= 2) {
if (getallen.get(0) < getallen.get(1)) {
return false;
} else {
getallen.remove(0);
return isDescending(getallen);
}
} else {
return true;
}
}
If I had to grade this, it would get a big fat X for
Having been fraudulently asked on stackoverflow
Being quite inefficient (try running this test on a list of a million elements, then realise that removing element 0 in an ArrayList causes all elements to shift down)
Instead consider:
public static boolean isDescending(List<Integer> getallen) {
return isDescending(getallen, 0);
}
public static boolean isDescending(List<Integer> getallen, int from) {
return from >= getallen.size() - 1
|| getallen.get(from) < getallen.get(from + 1)
&& isDescending(getallen, from + 1);
}
How about little bit more efficient approach with logarithmic recursion depth? Just as an exercise.
public static void main(String[] args) {
List<Integer> getallen = new ArrayList<Integer>();
getallen.add(500);
getallen.add(400);
getallen.add(300);
getallen.add(200);
getallen.add(100);
getallen.add(0);
System.out.println(isDescending(getallen));
}
public static boolean isDescending(List<Integer> getallen) {
return isDescending(getallen, 0, getallen.size());
}
private static boolean isDescending(List<Integer> getallen,
int start, int end) {
if (end - start <= 1)
return true;
if (end - start == 2) {
return getallen.get(start) > getallen.get(start + 1);
}
int middle = (start + end - 1) / 2 + 1;
return (getallen.get(middle - 1) > getallen.get(middle)) &&
isDescending(getallen, start, middle) &&
isDescending(getallen, middle, end);
}

Validate a String to see if it is an Integer?

Not keen on using the parseInteger solution, it is ugly, and as Joshua Bloch says you should "Use exceptions only for exceptional conditions". Of course, I can use something like block of code below, but it doesn't guarantee it is an Integer.
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
"Use exceptions only for exceptional conditions" is a good practice to follow in general, but it's not a hard-and-fast rule. I think that this is one of the cases where using exceptions is better than the alternatives.
Since parseInteger() can return any possible int value, you can't use any other return value to indicate failure. If you know you're never going to process a particular value (such as -1 or -2147483648), you can return that as a sentinel value to indicate a parse failure.
The only alternative is to return a boolean indicating success or failure and to store the parsed value into a parameter. However, since function calls are always pass-by-value in Java, you'd need to create a new class to do this:
public class IntWrapper
{
int value;
}
...
public static boolean myParseInt(String s, IntWrapper outValue)
{
try
{
outValue.value = Integer.parseInt(s);
return true;
}
catch(NumberFormatException e)
{
return false;
}
}
...
IntWrapper value = new IntWrapper();
if (myParseInt(value))
{
// Use value.value
}
else
{
// Parsing failed
}
Given these alternatives, I think the simplest usage is just to use exceptions and deal with them appropriately, even though non-numeric input may not necessary be an "exceptional" condition.
I'd leave it with exception but if you REALLY want solution without exception you can copy method parseInt() from this site with java internal classes and change it a little bit
(You can modify it a little bit more, since you do not need result)
public static false isValidInt(String s, int radix)
throws NumberFormatException
{
if (s == null) {
return false;
}
if (radix < Character.MIN_RADIX) {
return false;
}
if (radix > Character.MAX_RADIX) {
return false;
}
int result = 0;
boolean negative = false;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else
return false;
if (len == 1) // Cannot have lone "-"
return false;
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
return false;
}
if (result < multmin) {
return false;
}
result *= radix;
if (result < limit + digit) {
return false;
}
result -= digit;
}
} else {
return false;
}
return true;
}
You could use:
public static boolean isInteger(String str) {
if (str == null) {
return false;
}
int length = str.length();
if (length == 0) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length == 1) {
return false;
}
i = 1;
}
for (; i < length; i++) {
char c = str.charAt(i);
if (c <= '/' || c >= ':') {
return false;
}
}
return true;
}
Already answered here: What's the best way to check to see if a String represents an integer in Java?

Ordering Strings in java [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have an assignment where i am supposed to create an object that initializes an array of strings to have "size" elements and the amount of used elements equal to 0.
my issue is when im trying to compare strings to put them in alphabetical order.
int compare = storage[index].compareTo(value);
if (compare < 0)
thats where i am getting the runtime error of a nullpointerexception
here is my full code.
class main
package assignment2;
public class Main {
public static void main(String[] args) {
OrderedStringList myList = new OrderedStringList(5);
System.out.println("adding 10, 5, & 7");
myList.Insert("10");
myList.Insert("5");
myList.Insert("7");
myList.Display();
System.out.println("Value 4 find = "+ myList.Find("4"));
System.out.println("Value 7 find = "+ myList.Find("7"));
System.out.println("Adding 24 & 3");
myList.Insert("24");
myList.Insert("3");
myList.Display();
System.out.println("myList size: "+ myList.Size());
if (!myList.Insert("12"))
System.out.println("Could not add 12, full");
System.out.println("Removing 10, adding 12.");
myList.Delete("10");
myList.Insert("12");
myList.Display();
}
}
class OrderedStringList
package assignment2;
public class OrderedStringList {
int length;
int numUsed;
String[] storage;
boolean ordered;
public OrderedStringList(int size){
length = size;
storage = new String[length];
numUsed = 0;
}
public boolean Insert(String value){
boolean result = false;
int index = 0;
if (numUsed < length) {
while (index <= numUsed) {
int compare = storage[index].compareTo(value);
if (compare < 0)
index++;
}
moveItemsDown(index);
storage[index] = value;
numUsed++;
result = true;
}
return result;
}
private void moveItemsDown(int start){
int index;
for (index = numUsed-1; index >=start; index--){
storage[index+1] = storage[index];
}
}
private void moveItemsUp(int start){
int index;
for (index = start; index < numUsed-1; index++){
storage[index] = storage[index+1];
}
}
public boolean Find(String value){
return (FindIndex(value) >= 0);
}
private int FindIndex(String value) {
int result = -1;
int index = 0;
boolean found = false;
while ((index < numUsed) && (!found)) {
found = (value.equals(storage[index]));
if (!found)
index++;
}
if (found)
result = index;
return result;
}
public boolean Delete(String value){
boolean result = false;
int location;
location = FindIndex(value);
if (location >= 0) {
moveItemsUp(location);
numUsed--;
result = true;
}
return result;
}
public void Display() {
int index;
System.out.println("list Contents: ");
for (index = 0; index < numUsed; index++) {
System.out.println(index+" "+storage[index]);
}
System.out.println("-------------");
System.out.println();
}
public void DisplayNoLF() {
int index;
System.out.println("list Contents: ");
for (index = 0; index < numUsed; index++) {
System.out.print(storage[index]+" ");
}
System.out.println("-------------");
System.out.println();
}
public int Size(){
return numUsed;
}
}
thanks guys
It should be
while(index < numUsed)
If you use <=, you'll always access index 0 in an empty list, which will be null. Then when you try to call compareTo on it it will throw an NPE.
ALso, if null is a legal value to add to your list, you'll need to put a null check around the compareTo call and decide if null is alphabetically first or last.
You can use Arrays#sort to maintain order, its already available in library.
public boolean Insert(String value){
boolean result = false;
if (numUsed < length) {
storage[index] = value;
numUsed++;
result = true;
Arrays.sort(storage);
}
return result;
}
Here's why:
public boolean Insert(String value){
boolean result = false;
int index = 0;
if (numUsed < length) {
while (index <= numUsed) { // Here the first time numUsed = 0, index = 0, index <= numUsed;
int compare = storage[index].compareTo(value); // The first time, storage[0] == null; NullPointException is thrown
if (compare < 0)
index++;
}
moveItemsDown(index);
storage[index] = value;
numUsed++;
result = true;
}
return result;
}
Maybe change <= to < will do?
At the first run this line
int compare = storage[index].compareTo(value);
your are comparing storage[index] which value is null with value which is not null or empty
to enable a smooth running
replace
while(index =< numUsed) {
int compare = storage[index].compareTo(value);
if(compare < 0)
index++;
}
with
while(index < numUsed) {
int compare = storage[index].compareTo(value);
if(compare < 0)
index++;
}

Categories

Resources