I am writing a compararator to sort log lines:
Code:
public static final Comparator<String> HTMLcomparator = new Comparator<String>()
{
#Override
public int compare(String line1, String line2)
{
HTMLLogLine htmlLogLine1 = new HTMLLogLine(line1);
HTMLLogLine htmlLogLine2 = new HTMLLogLine(line2);
int fullCompare = 0;
String requestId1 = htmlLogLine1.getRequestId();
String requestId2 = htmlLogLine2.getRequestId();
if(requestId1 != null && requestId2 != null)
{
fullCompare = requestId1.compareTo(requestId2);
}
else if(requestId1 == null && requestId2 != null)
{
fullCompare = -1;
}
else if(requestId1 != null)
{
fullCompare = 1;
}
else
{
fullCompare = 0;
}
if(fullCompare == 0)
{
String security1 = htmlLogLine1.getSecurity();
String security2 = htmlLogLine2.getSecurity();
if(security1 != null && security2 != null)
{
fullCompare = security1.compareTo(security2);
}
else if(security1 == null && security2 != null)
{
fullCompare = -1;
}
else if(security1 != null && security2 == null)
{
fullCompare = 1;
}
else
{
fullCompare = 0;
}
}
if(fullCompare == 0)
{
String scenario1 = htmlLogLine1.getScenario();
String scenario2 = htmlLogLine2.getScenario();
if(scenario1 != null && scenario2 != null)
{
fullCompare = scenario1.compareTo(scenario2);
}
else if(scenario1 == null && scenario2 != null)
{
fullCompare = -1;
}
else if(scenario1 != null)
{
fullCompare = 1;
}
else
{
fullCompare = 0;
}
}
if(fullCompare == 0)
{
Optional<Instant> timestamp1 = htmlLogLine1.getTimestamp();
Optional<Instant> timestamp2 = htmlLogLine2.getTimestamp();
if(timestamp1.isPresent() && timestamp2.isPresent())
{
fullCompare = timestamp1.get().compareTo(timestamp2.get());
}
else if(!timestamp1.isPresent() && timestamp2.isPresent())
{
fullCompare = -1;
}
else if(timestamp1.isPresent() && !timestamp2.isPresent())
{
fullCompare = 1;
}
else
{
fullCompare = 0;
}
}
return fullCompare;
}
};
The code seems very naive and has a lot of duplication. Any ideas how to make it concise?
Previous to this code, I had written the following code in compare method:
Comparator<HTMLLogLine > fullComparator = Comparator.comparing(HTMLLogLine ::getRequestId)
.thenComparing(HTMLLogLine ::getSecurity)
.thenComparing(HTMLLogLine ::getScenario);
fullCompare = fullComparator.compare(logLine1, logLine2);
However,to my surprise the code threw exception: Compare method does not follow the contract!
How can I make this comparator concise yet make it work?
Related
The below code has many duplicate lines, looking for a short thing for this.
if(null!= commonShipmentSplInstr.getIsGiftOrder() && GIFT_ORDER_FLAG.equalsIgnoreCase(commonShipmentSplInstr.getIsGiftOrder())) {
printObj.setDOCUMENT(INVOICE_DOCUMENT_FOR_PROSHIP_GIFT_ORDER);
giftMessageLine1 = commonShipmentSplInstr.getGiftMessageLine1();
giftMessageLine2 = commonShipmentSplInstr.getGiftMessageLine2();
giftMessageLine3 = commonShipmentSplInstr.getGiftMessageLine3();
} else if(null!= commonShipmentSplInstr.getSplInstr6() && GIFT_ORDER_FLAG.equalsIgnoreCase(commonShipmentSplInstr.getSplInstr6())) {
printObj.setDOCUMENT(INVOICE_DOCUMENT_FOR_PROSHIP_GIFT_ORDER);
giftMessageLine1 = commonShipmentSplInstr.getGiftMessageLine1();
giftMessageLine2 = commonShipmentSplInstr.getGiftMessageLine2();
giftMessageLine3 = commonShipmentSplInstr.getGiftMessageLine3();
} else if (null != sellingChannel && InvoiceHelper.isZolaSellingChannel(sellingChannel)) {
printObj.setDOCUMENT(INVOICE_DOCUMENT_FOR_PROSHIP_ZOLA_ORDER);
} else {
printObj.setDOCUMENT(DOCUMENT_FOR_PRINT_INVOICE_LABEL_FOR_PROSHIP);
}
In the setDOCUMENT method, all are Constants.
Just combine the two first if clause into one, they seem to be doing exactly the same:
if(commonShipmentSplInstr != null && (GIFT_ORDER_FLAG.equalsIgnoreCase(commonShipmentSplInstr.getIsGiftOrder()) || GIFT_ORDER_FLAG.equalsIgnoreCase(commonShipmentSplInstr.getSplInstr6()))) {
printObj.setDOCUMENT(INVOICE_DOCUMENT_FOR_PROSHIP_GIFT_ORDER);
giftMessageLine1 = commonShipmentSplInstr.getGiftMessageLine1();
giftMessageLine2 = commonShipmentSplInstr.getGiftMessageLine2();
giftMessageLine3 = commonShipmentSplInstr.getGiftMessageLine3();
}
else if (null != sellingChannel && InvoiceHelper.isZolaSellingChannel(sellingChannel)) {
printObj.setDOCUMENT(INVOICE_DOCUMENT_FOR_PROSHIP_ZOLA_ORDER);
}
else {
printObj.setDOCUMENT(DOCUMENT_FOR_PRINT_INVOICE_LABEL_FOR_PROSHIP);
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I'm writing a program that creates an infinitely long integer by making each number in the integer its own node.
For example: 123,456 = [1]->[2]->[3]->[4]->[5]->[6]
Also, I need to be able to add the contents of two infinite integers together.
For example: [1]->[2]->[3]->[4]->[5]->[6] + [1]->[2]->[3]
= [1]->[2]->[3]->[5]->[7]->[9]
However, when I try to reversely traverse one of the linked lists, I get a NullPointerException after the first loop through;
while((currentOne != null) && (currentTwo != null)) {
// for(int i = firstOperand.getNumberOfDigitsWithZeroes(); i>0; i--)
if(currentOne.data > currentTwo.data) {
tempResult = currentOne.data - currentTwo.data;
//result = tempResult + result;
returnResult.addToFront(tempResult);
} else if(currentOne.data < currentTwo.data) {
currentOne.previous.data -= 1;
currentOne.data += 10;
tempResult = currentOne.data - currentTwo.data;
//result = tempResult + result;
returnResult.addToFront(tempResult);
} else if((currentOne == firstOperand.firstNode && currentTwo == secondOperand.firstNode) &&
currentOne.data - currentTwo.data == 0) {
break;
} else {
returnResult.addToFront(0);
}
currentOne = currentOne.previous;
currentTwo = currentTwo.previous;
}
firstOperand is the linked list of the number 100000000000000000000. currentOne is a node initialized to the last node of the firstOperand. currentTwo is a node initialized to the last node of the secondOperand which has the contents of 000000000000000000001. The error is located in the line
if(currentOne.data > currentTwo.data)
The error occurs after only the second run through of the loop, and i'm not sure why, because when printed in string form, the secondOperand shows the full 000000000000000000001. So, I'm not sure why i'm getting the null pointer exception instead of currentTwo.data being equal to 0.
Here is the constructor for an InfiniteInteger object
public LInfiniteInteger(String s)
{
// TO DO
int newDigit = 0;
isNegative = false;
numberOfDigits = 0;
middlePosition = 0;
firstNode = null;
middleNode = null;
lastNode =null;
for(int i =0; i<s.length(); i++)
{
newDigit = (int)s.charAt(i) - 48;
if((newDigit >= 0) && (newDigit <= 9))
{
// this.add(newDigit);
if(firstNode == null)
{
firstNode = new Node(null, newDigit, null);
lastNode = firstNode;
}
else
{
Node newNode = new Node(lastNode, newDigit, null);
lastNode.next = newNode;
lastNode = newNode;
}
numberOfDigits++;
if(numberOfDigits %2 == 1);
{
if(middleNode == null)
{
middleNode = firstNode;
}
else
{
middleNode = middleNode.next;
}
middlePosition++;
}
}
else if((newDigit == ((int)'-') - 48))
{
isNegative = true;
}
}
}
This is the full method of where the error occurs:
public InfiniteIntegerInterface minus(final InfiniteIntegerInterface anInfiniteInteger)
{
// TO DO
LInfiniteInteger firstOperand = new LInfiniteInteger(this.toString());
LInfiniteInteger secondOperand = new LInfiniteInteger(anInfiniteInteger.toString());
LInfiniteInteger returnResult = new LInfiniteInteger("");
int tempResult;
boolean resultIsNegative = false;
Node currentOne = firstOperand.lastNode;
Node currentTwo = secondOperand.lastNode;
while(firstOperand.getNumberOfDigitsWithZeroes() > secondOperand.getNumberOfDigitsWithZeroes())
{
Node temp = new Node(0);
temp.next=secondOperand.firstNode;
secondOperand.firstNode = temp;
secondOperand.addNumberOfDigits();
}
while(firstOperand.getNumberOfDigitsWithZeroes() < secondOperand.getNumberOfDigitsWithZeroes())
{
Node temp = new Node(0);
temp.next=firstOperand.firstNode;
firstOperand.firstNode = temp;
firstOperand.addNumberOfDigits();
}
if((firstOperand.isNegative == false) && (secondOperand.isNegative == false))
{
if(firstOperand.compareMag(secondOperand) == 1)
{
//algorithm
//System.out.println(currentTwo.data);
//System.out.println(secondOperand.toString());
for(int i = secondOperand.getNumberOfDigitsWithZeroes(); i > 0; i--)
{
System.out.println(currentOne.data);
currentOne = currentOne.previous;
}
currentOne = firstOperand.lastNode;
while((currentOne != null) && (currentTwo != null))
// for(int i = firstOperand.getNumberOfDigitsWithZeroes(); i>0; i--)
{
if(currentOne.data > currentTwo.data)
{
tempResult = currentOne.data - currentTwo.data;
//result = tempResult + result;
returnResult.addToFront(tempResult);
}
else if(currentOne.data < currentTwo.data)
{
currentOne.previous.data -= 1;
currentOne.data += 10;
tempResult = currentOne.data - currentTwo.data;
//result = tempResult + result;
returnResult.addToFront(tempResult);
}
else if((currentOne == firstOperand.firstNode && currentTwo == secondOperand.firstNode) && currentOne.data - currentTwo.data == 0)
{
break;
}
else
{
returnResult.addToFront(0);
}
currentOne = currentOne.previous;
currentTwo = currentTwo.previous;
}
if(currentOne == null)
{
while(currentTwo != null)
{
//result = currentTwo.data + result;
returnResult.addToFront(currentTwo.data);
currentTwo = currentTwo.previous;
}
}
else if(currentTwo == null)
{
while(currentTwo != null)
{
//result = currentTwo.data + result;
returnResult.addToFront(currentTwo.data);
currentTwo = currentTwo.previous;
}
}
return returnResult;
}
else if(firstOperand.compareMag(secondOperand) == 0)
{
returnResult.add(0);
return returnResult;
}
else
{
LInfiniteInteger tempReturnResult = new LInfiniteInteger(secondOperand.minus(firstOperand).toString());
Node currentOneInner = tempReturnResult.firstNode;
while(currentOneInner != null)
{
returnResult.add(currentOneInner.data);
currentOneInner = currentOneInner.next;
}
returnResult.isNegative = true;
return returnResult;
}
}
else if((firstOperand.isNegative == false) && (secondOperand.isNegative == true))
{
secondOperand.isNegative = false;
LInfiniteInteger tempReturnResult = new LInfiniteInteger(firstOperand.plus(secondOperand).toString());
Node currentOneInner = tempReturnResult.firstNode;
while(currentOneInner != null)
{
returnResult.add(currentOneInner.data);
currentOneInner = currentOneInner.next;
}
return returnResult;
}
else if((firstOperand.isNegative == true) && (secondOperand.isNegative == false))
{
firstOperand.isNegative = false;
LInfiniteInteger tempReturnResult = new LInfiniteInteger(firstOperand.plus(secondOperand).toString());
Node currentOneInner = tempReturnResult.firstNode;
while(currentOneInner != null)
{
returnResult.add(currentOneInner.data);
currentOneInner = currentOneInner.next;
}
returnResult.isNegative = true;
return returnResult;
}
else
{
if(firstOperand.compareMag(secondOperand) == -1)
{
firstOperand.isNegative = false;
secondOperand.isNegative = false;
LInfiniteInteger tempReturnResult = new LInfiniteInteger(firstOperand.minus(secondOperand).toString());
Node currentOneInner = tempReturnResult.firstNode;
while(currentOneInner != null)
{
returnResult.add(currentOneInner.data);
currentOneInner = currentOneInner.next;
}
return returnResult;
}
else if(firstOperand.compareMag(secondOperand) == 0)
{
returnResult.add(0);
return returnResult;
}
else
{
firstOperand.isNegative = false;
secondOperand.isNegative = false;
LInfiniteInteger tempReturnResult = new LInfiniteInteger(firstOperand.minus(secondOperand).toString());
Node currentOneInner = tempReturnResult.firstNode;
while(currentOneInner != null)
{
returnResult.add(currentOneInner.data);
currentOneInner = currentOneInner.next;
}
returnResult.isNegative = true;
return returnResult;
}
}
}
I'm trying to subtract 1000000000000000 and 0000000000000001.
Here's my Node class:
private class Node
{
private int data;
private Node next;
private Node previous;
private Node(Node previousNode, int aData, Node nextNode)
{
previous = previousNode;
data = aData;
next = nextNode;
}
private Node(int aData)
{
this(null, aData, null);
}
}
The problem may happens because you fail to initialize the member variable data. Check your code carefully and debug it step by step.
Your constructor doesn't take care of member previous, or is this in the Node constructor?
I'm implementing the Servlet URL pattern matching follow the Servlet Specification. My matching method:
public static boolean match(String pattern, String str, boolean isCaseSensitive) {
char[] patArr = pattern.toCharArray();
char[] strArr = str.toCharArray();
int patIdxStart = 0;
int patIdxEnd = patArr.length - 1;
int strIdxStart = 0;
int strIdxEnd = strArr.length - 1;
boolean containsStar = false;
for (int i = 0; i < patArr.length; i++) {
if (patArr[i] != '*') {
continue;
}
containsStar = true;
break;
}
if (!containsStar) {
if (patIdxEnd != strIdxEnd) {
return false;
}
for (int i = 0; i <= patIdxEnd; i++) {
char ch = patArr[i];
if (ch == '?')
continue;
if ((isCaseSensitive) && (ch != strArr[i])) {
return false;
}
if ((!isCaseSensitive)
&& (Character.toUpperCase(ch) != Character
.toUpperCase(strArr[i]))) {
return false;
}
}
return true;
}
if (patIdxEnd == 0) {
return true;
}
char ch;
while (((ch = patArr[patIdxStart]) != '*')
&& (strIdxStart <= strIdxEnd)) {
if (ch != '?') {
if ((isCaseSensitive) && (ch != strArr[strIdxStart])) {
return false;
}
if ((!isCaseSensitive)
&& (Character.toUpperCase(ch) != Character
.toUpperCase(strArr[strIdxStart]))) {
return false;
}
}
patIdxStart++;
strIdxStart++;
}
if (strIdxStart > strIdxEnd) {
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}
while (((ch = patArr[patIdxEnd]) != '*') && (strIdxStart <= strIdxEnd)) {
if (ch != '?') {
if ((isCaseSensitive) && (ch != strArr[strIdxEnd])) {
return false;
}
if ((!isCaseSensitive)
&& (Character.toUpperCase(ch) != Character
.toUpperCase(strArr[strIdxEnd]))) {
return false;
}
}
patIdxEnd--;
strIdxEnd--;
}
if (strIdxStart > strIdxEnd) {
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}
while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) {
int patIdxTmp = -1;
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
continue;
}
patIdxTmp = i;
break;
}
if (patIdxTmp == patIdxStart + 1) {
patIdxStart++;
continue;
}
int patLength = patIdxTmp - patIdxStart - 1;
int strLength = strIdxEnd - strIdxStart + 1;
int foundIdx = -1;
for (int i = 0; i <= strLength - patLength; i++) {
int j = 0;
while (true)
if (j < patLength) {
ch = patArr[(patIdxStart + j + 1)];
if (ch != '?') {
if ((isCaseSensitive)
&& (ch != strArr[(strIdxStart + i + j)])) {
break;
}
if ((!isCaseSensitive)
&& (Character.toUpperCase(ch) != Character
.toUpperCase(strArr[(strIdxStart
+ i + j)])))
break;
} else {
j++;
continue;
}
} else {
foundIdx = strIdxStart + i;
break;
}
}
if (foundIdx == -1) {
return false;
}
patIdxStart = patIdxTmp;
strIdxStart = foundIdx + patLength;
}
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}
But when I test with case below:
String pattern = "*.a*";
String path = "/index.abc";
String matches = match(pattern, path, true) ? "matches" : "unmatches";
System.out.println(path + " " + matches + " " + pattern);
The test case runs forever and cannot stop. I have 2 questions:
Is pattern "*.a*" valid with Servlet URL pattern matching spec?
How to fix this error to break the infinite loop?
Here is my Java Servlet Specification 3.1 (April 2013) Mapping Requests to Servlets implementation.
/**
* Java Servlet Specification 3.1 (April 2013)
* Mapping Requests to Servlets (Chapter 12) implementation.
*
* This class is thread safe.
*/
public class ServletMappingMatcher {
private final String[] patterns;
private final String[] welcomePages;
public ServletMappingMatcher(String... patterns) {
this(patterns, new String[0]);
}
public ServletMappingMatcher(String[] patterns, String[] welcomePages) {
this.patterns = patterns;
this.welcomePages = welcomePages;
}
public String getPatternForPath(String path) {
for (String pattern : patterns) {
if (matches(pattern, path)) {
return pattern;
}
}
return null;
}
private boolean matches(String pattern, String path) {
if (isPathMapping(pattern)) {
return pathMatches(pattern, path);
} else if (isExtensionPattern(pattern)) {
return extensionMatches(pattern, path);
} else if (isApplicationContextRoot(pattern)) {
return matchesApplicationContextRoot(path);
} else if (isDefaultServlet(pattern)) {
return matchesDefaultServlet(path);
}
return strictlyMatches(pattern, path);
}
private boolean isPathMapping(String pattern) {
return pattern.startsWith("/") && pattern.endsWith("/*");
}
private boolean isExtensionPattern(String pattern) {
return pattern.startsWith("*.");
}
private boolean isApplicationContextRoot(String pattern) {
return pattern.isEmpty();
}
private boolean isDefaultServlet(String pattern) {
return pattern.equals("/");
}
private boolean pathMatches(String pattern, String path) {
return path.startsWith(pattern.substring(0, pattern.length() - 1)) ||
path.equals(pattern.substring(0, pattern.length() - 2));
}
private boolean extensionMatches(String pattern, String path) {
return path.endsWith(pattern.substring(1));
}
private boolean matchesApplicationContextRoot(String path) {
return path.equals("/");
}
private boolean strictlyMatches(String pattern, String path) {
return path.equals(pattern);
}
private boolean matchesDefaultServlet(String path) {
if (path.endsWith("/")) {
return true;
}
for (String welcomePage : welcomePages) {
if (path.endsWith("/" + welcomePage)) {
return true;
}
}
return false;
}
}
And JUnit tests:
import org.junit.Assert;
import org.junit.Test;
public class ServletMappingMatcherTest {
#Test
public void testsFromSpec() {
final String servlet1Pattern = "/foo/bar/*";
final String servlet2Pattern = "/baz/*";
final String servlet3Pattern = "/catalog";
final String servlet4Pattern = "*.bop";
final String defaultServlet = "/";
final String[] patterns = {servlet1Pattern, servlet2Pattern, servlet3Pattern, servlet4Pattern, defaultServlet};
final String[] welcomePages = {"index.html"};
final ServletMappingMatcher matcher = new ServletMappingMatcher(patterns, welcomePages);
Assert.assertEquals(servlet1Pattern, matcher.getPatternForPath("/foo/bar/index.html"));
Assert.assertEquals(servlet1Pattern, matcher.getPatternForPath("/foo/bar/index.bop"));
Assert.assertEquals(servlet2Pattern, matcher.getPatternForPath("/baz"));
Assert.assertEquals(servlet2Pattern, matcher.getPatternForPath("/baz/index.html"));
Assert.assertEquals(servlet3Pattern, matcher.getPatternForPath("/catalog"));
Assert.assertEquals(defaultServlet, matcher.getPatternForPath("/catalog/index.html"));
Assert.assertEquals(servlet4Pattern, matcher.getPatternForPath("/catalog/rececar.bop"));
Assert.assertEquals(servlet4Pattern, matcher.getPatternForPath("/index.bop"));
}
}
I fixed it, in the while(true) loop add below line to break the loop:
[...]
while(true) {
if (ch != '?') {
if(...) {
//...
break;
}
if(...) {
//...
break;
}
j++; // Add this line to avoid infinite loop
}
}
private byte isTargetEast(IRobot robot) {
byte resultE = 0;
if (robot.getLocation().x > robot.getTargetLocation().x) {
resultE = -1;
} else if (robot.getLocation().x < robot.getTargetLocation().x) {
resultE = 1;
} else {
resultE = 0; }
return resultE;
// returning 1 for 'yes', -1 for 'no' and 0 for 'same latitude'.
}
gives errors 'erro: illegal start of expression' and 'error ';' expected, 6 errors total, 2 illegal starts, 4semicolons, all on the private byte line
The syntax of the if-condition is totally wrong. What you want to do? You are mixing assign and condition code.
You can do assign like this:
if (chanceDir >= 0.5) {
Dir = IRobot.AHEAD;
Vir = IRobot.BEHIND;
Hir = IRobot.AHEAD;
Sir = IRobot.BEHIND;
} else {
Dir = IRobot.RIGHT;
Vir = IRobot.LEFT;
Hir = IRobot.LEFT;
Sir = IRobot.RIGHT;
}
if (oppchanceDir >= 0.5) {
Dir = IRobot.BEHIND;
Vir = IRobot.AHEAD;
Hir = IRobot.BEHIND;
Sir = IRobot.AHEAD;
}else {
Dir = IRobot.LEFT;
Vir = IRobot.RIGHT;
Hir = IRobot.RIGHT;
Sir = IRobot.LEFT;
}
Or you can do check conditions like that:
if (chanceDir >= 0.5 && ((Dir == IRobot.AHEAD) && (Vir == IRobot.BEHIND) && (Hir == IRobot.AHEAD) && (Sir == IRobot.BEHIND))) {
// do something here
}else if((Dir == IRobot.RIGHT) && (Vir == IRobot.LEFT) && (Hir == IRobot.LEFT) && (Sir == IRobot.RIGHT)){
// do something here
}else{
// do something here
}
if (oppchanceDir >= 0.5 && ((Dir == IRobot.BEHIND) && (Vir == IRobot.AHEAD) && (Hir == IRobot.BEHIND) && (Sir == IRobot.AHEAD))) {
// do something here
} else if ((Dir == IRobot.LEFT) && (Vir == IRobot.RIGHT) && (Hir == IRobot.RIGHT) && (Sir == IRobot.LEFT)) {
// do something here
}else{
// do something here
}
I have a class Contact with fields firstName, lastName and emails. I need to sort them using Collection.sort(...), but I got an exception:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
My compareTo method:
#Override
public int compareTo(Contact another) {
int compareFirstName = 0;
if (this.getFirstName() != null && another.getFirstName() != null) {
compareFirstName = this.getFirstName().compareToIgnoreCase(
another.getFirstName());
if (compareFirstName == 0) {
int compareLastName = 0;
if (this.getLastName() != null && another.getLastName() != null) {
compareLastName = this.getLastName().compareToIgnoreCase(
another.getLastName());
if (compareLastName == 0) {
int compareEmail = 0;
if (this.getEmails() != null
&& another.getEmails() != null) {
compareEmail = this.getEmails()
.compareToIgnoreCase(another.getEmails());
return compareEmail;
} else {
return 0;
}
} else {
return compareLastName;
}
} else {
int compareEmail = 0;
if (this.getEmails() != null && another.getEmails() != null) {
compareEmail = this.getEmails().compareToIgnoreCase(
another.getEmails());
return compareEmail;
} else {
return 0;
}
}
} else {
return compareFirstName;
}
} else {
int compareLastName = 0;
if (this.getLastName() != null && another.getLastName() != null) {
compareLastName = this.getLastName().compareToIgnoreCase(
another.getLastName());
if (compareLastName == 0) {
int compareEmail = 0;
if (this.getEmails() != null && another.getEmails() != null) {
compareEmail = this.getEmails().compareToIgnoreCase(
another.getEmails());
return compareEmail;
} else {
return 0;
}
} else {
return compareLastName;
}
} else {
int compareEmail = 0;
if (this.getEmails() != null && another.getEmails() != null) {
compareEmail = this.getEmails().compareToIgnoreCase(
another.getEmails());
return compareEmail;
} else {
return 0;
}
}
}
}
Please help me to find error in my compareTo method. Thanks.
Your implementation does violate the contract.
Suppose you have 3 Contacts :
contact1 : First Name = "John", Last Name = "Doe", Email = "x#gmail.com"
contact2 : First Name = "John", Last Name = "Doe", Email = null
contact3 : First Name = "John", Last Name = null, Email = "y#gmail.com"
Based on your logic :
contact1.compareTo(contact2) returns 0 (since they have the same first and last name).
contact2.compareTo(contact3) also returns 0 (since you only compare by first name).
But contact1.compareTo(contact3) doesn't return 0 (since they have different emails).
compareTo must be transitive.
The way to fix this is not to ignore a property that is null only in one of the contacts you are comparing. For example, if this.getLastName()==null && another.getLastName() != null, return 1 (assuming you want to order the null last names after the non-null last names).