Best way to check NULL for objects in Java - java

I have a solution to check NULL values extracted from object, However i feel there might be best approach than i am doing here. So please suggest me the best ways with code snippet :)
I will be passing my xml Content to unmarshalling method & then pass the unmarshalledValues to null check method (i.e ValidateInputFiled )
Contents unmarshalledValues = unmarshalingContent( xml );
inputCheck = ValidateInputField( unmarshalledValues );
I have a POJO for my XML elements as mentioned below,
#XmlRootElement( name = "contents" )
public class Contents
{
#XmlElement
String A;
#XmlElement
String B;
#XmlElement
String C;
#XmlAttribute
String D;
public String getA()
{
return A;
}
public String getB()
{
return B;
}
public String getC()
{
return C;
}
public String getD()
{
return D;
}
}
I have defined ValidateInputFiled as mentioned below
public Boolean ValidateInputField( Contents unmarshalledValues )
{
int checker = 0;
Boolean listCheck = false;
// Extracting unmarshalled values from xml
String A= unmarshalledValues.getA();
String B= unmarshalledValues.getB();
String C = unmarshalledValues.getC();
String D= unmarshalledValues.getD();
if ( A== null || A.isEmpty() )
{
checker++;
}
if ( B== null || B.isEmpty() )
{
checker++;
}
if ( C== null || C.isEmpty() )
{
checker++;
}
if ( D== null || D.isEmpty() )
{
checker++;
}
if ( checker == 0 )
{
listCheck = true;
}
return listCheck;
}
Here i am looking to avoid NULL check for each String Values ( i.e A, B, C, D ) instead can i just do null check for Contents or for unmarshalledValues using collection or list ?

public static boolean isNullOrEmpty(String a) {
return a == null || a.isEmpty();
}
Call that for each value. You may want to think about adding them all to a list and then iterating through them, incrementing checker if they're !isNullOrEmpty to save code bloat if you have lots for fields.
PS: Make your fields private to preserve encapsulation.
pps: don't bother with a seperate boolean just return checker == 0; to keep the code neat.

Is that what you are looking for ?
public Boolean ValidateInputField(Contents unmarshalledValues) {
// Extracting unmarshalled values from xml
String A = unmarshalledValues.getA();
String B = unmarshalledValues.getB();
String C = unmarshalledValues.getC();
String D = unmarshalledValues.getD();
return checkNull(A, B, C, D);
}
private static boolean checkNull(String... strings) {
for (String string : strings) {
if (string == null || string.isEmpty()) {
return false;
}
}
return true;
}

I use the apache commons StringUtils library for this type of thing. It has a check that includes null or empty spaces, plus other combinations depending on how you treat empty spaces. Pretty much code like Jeff here gave you, but i like having other methods they include.
You can also avoid nulls alltogether by coding your getters to return "" if a value == null. Then you would not have to check each field for null.

commons-lang has a Validate class you could use:
Validate.notNull( unmarshalledValues.getA() );

Non-reflective solution for Java 8, without using a series of if's, would be to stream all fields and check for nullness:
return Stream.of(id, name).allMatch(Objects::isNull);
This remains quite easy to maintain while avoiding the reflection hammer. This will return true for null attributes.

Related

Comparing two objects names in an equals method

I'm a little lost on how to correctly compare objects that I'm testing. My issue is that the tests themselves always come out as true due to the code, but any other way I think of doesn't work correctly either.
public class Element {
private String atomLetter;
private String name;
public Element(String atomLetter, String name) {
this.atomLetter = atomLetter.toUpperCase();
this.name = name.toLowerCase();
}
public Element(String atomLetter) {
this(atomLetter, "");
}
public String getAtomLetter() {
return atomLetter;
}
public String getName() {
return name;
}
// TODO: two elements are considered to be equal if they have the same atom letter.
#Override
public boolean equals(final Object obj) {
if (atomLetter == this.atomLetter){
return true;
}
return false;
}
#Override
public String toString() {
return "Element{" +
"'" + atomLetter + "'" +
", name='" + name + '\'' +
'}';
}
}
In this case, the outcome comes out exactly the same, but the issue is the equals method.
#Test
public void testSimpleMolecules() {
// simple carbon
Molecule m1 = new Molecule("");
assertTrue(m1.isEmpty());
assertEquals(0, m1.size());
m1.add(new Element("C"));
assertFalse(m1.isEmpty());
assertEquals(1, m1.size());
assertEquals(new Element("C"), m1.get(0));
// simple hydrogen
Molecule m2 = new Molecule("");
m2.add(new Element("H"));
assertFalse(m2.isEmpty());
assertEquals(1, m2.size());
assertEquals(new Element("H"), m2.get(0));
// simple nitrogen
Molecule m3 = new Molecule("");
m3.add(new Element("N"));
assertFalse(m3.isEmpty());
assertEquals(1, m3.size());
assertEquals(new Element("N"), m3.get(0));
// simple oxygen
Molecule m4 = new Molecule("");
m4.add(new Element("O"));
assertFalse(m4.isEmpty());
assertEquals(1, m4.size());
assertEquals(new Element("O"), m4.get(0));
}
In your equals method, you are comparing this object's atomLetter to itself.
if (atomLetter == this.atomLetter){
Instead, you need to cast the obj argument to the Element class and compare its atomLetter to this.atomLetter
Element other = (Element) obj;
return this.atomLettet == other.atomLettet;
Of course, you'll likely want to test that the cast is possible before actually doing it, and say that the objects are not equal if they are of different classes. Also test for null. The javadoc for object.Equals() explains all if the requirements for a proper equals method.
The Answer by DarkSigma is correct about your comparison of this.atomLetter to itself. You have a few other issues with your equals.
Compare content, not references
Your code … == this.atomLetter is comparing object references (pointers) rather than the textual content of those String objects. In other words, you are asking if the two variables both refer to the same object, that is, the same chunk of memory.
Always compare String content by calling String::equals or String::equalsIgnoreCase.
For implementing equals, you can test for references being the same, as a quick first part of the equality testing. But this alone is not enough.
if ( this == other ) return true;
Test for null
You should test for null. If the other object reference is null, there is no object, so there can be no equality.
if ( other == null ) return false;
Test for class
You can also make sure the class of the two objects match.
if ( other == null || getClass() != other.getClass() ) return false;
Cast
As the other Answer mentioned, you should cast the passed Object, having gotten past the class-matching test shown above.
Element element = ( Element ) other;
Check for matching content
As the last test, check for matching content.
In this particular case, I suspect you do care about case matching. So we call String::equals rather than String::equalsIgnoreCase.
return getAtomLetter().equals( element.getAtomLetter() );
Example equals method
Let's pull that all together into a single equals implementation.
#Override
public boolean equals ( Object other )
{
if ( this == other ) return true;
if ( other == null || getClass() != other.getClass() ) return false;
Element element = ( Element ) other;
return getAtomLetter().equals( element.getAtomLetter() );
}
Tip: Your IDE will generate this code for you. No need to write this yourself. For example, in IntelliJ, choose: Code > Generate > equals() and hashCode.
Always implement hashCode when implementing equals
As discussed many times on Stack Overflow, such as here, when writing an equals method, always write a hashCode method using the same logic.
#Override
public int hashCode ( )
{
return Objects.hash( getAtomLetter() );
}
Example class
So we end up with a Element class that looks like this.
package work.basil.example;
import java.util.Objects;
public class Element
{
// Member fields
private String atomLetter, name;
// Constructor
public Element ( String atomLetter , String name )
{
this.atomLetter = Objects.requireNonNull( atomLetter ).toUpperCase();
if ( this.atomLetter.isBlank() ) { throw new IllegalArgumentException();}
this.name = Objects.requireNonNull( name ).toLowerCase();
}
// Getters (read-only).
public String getAtomLetter ( ) {return atomLetter;}
public String getName ( ) {return name;}
// `Object` overrides
#Override
public boolean equals ( Object other )
{
if ( this == other ) return true;
if ( other == null || getClass() != other.getClass() ) return false;
Element element = ( Element ) other;
return getAtomLetter().equals( element.getAtomLetter() );
}
#Override
public int hashCode ( )
{
return Objects.hash( getAtomLetter() );
}
#Override
public String toString ( )
{
return "Element{ " +
"atomLetter='" + atomLetter + '\'' +
" | name='" + name + '\'' +
" }";
}
}
You can implement the equals method this way. However, you also have to implement hashCode for correctness.
For equals
#Override
public boolean equals(Object obj)
{
// check the instance of obj
if (!(obj instanceof Element)) return false;
// check if obj is itself
if (obj == this) return true;
// cast obj as Element
Element e = (Element) obj;
// compare fields
return this.atomLetter.equals(e.atomLetter) &&
this.name.equals(e.name);
}
For hashcode, you can implement it a number of ways, but usually this is the quickest and easiest way.
#Override
public int hashCode()
{
return Objects.hash(atomLetter, name);
}

Suspicious call to Collection.contains method in ArrayList

I am getting a warning that watchStore.contains(s) is a suspicious call to java.util.Collection#contains. How can I fix it? I want to use contains() to find a particular object with the matching serial number.
public Watch findWatchBySerialNumber(long srch) {
long s = srch;
Watch watch = null;
for(int i = 0; i < watchStore.size(); i++) {
watch = watchStore.get(i);
if(watchStore.contains(s)) {
System.out.print("item found");
return watch;
}
}
System.out.print("item not found");
return null; // watch is not found.
}
Presuming that Watch is the class, watchStore is a List<Watch>, and that a field serialNo exists on Watch...
public Optional<Watch> findWatchBySerialNumber(long serial) {
return watchStore.stream()
.filter(w -> w.getSerialNo() == serial)
.findFirst();
}
If you're not using Java 8, the code is close, but a bit more dangerous since you have the chance to return null. If you can use Guava's Optional, that'd be a better choice here.
public Watch findWatchBySerialNumber(long serial) {
for(Watch w : watchStore) {
if(w.getSerialNo() == serial) {
return w;
}
}
return null;
}
Your contains isn't going to work since your list doesn't contain Longs, it contains Watchs. This is also why the compiler sees it as dubious; contains accepts an Object but it will return false if what you're looking for doesn't have a comparable equals for what's in your list.
You have to iterate over the entirety of your collection to find it in this scenario, especially since you're looking for a specific property on those objects as opposed to a specific, easy-to-provide value.
please how can I fix that. I want to use the contain() to find a
particular object with the matching serial number.
In that case override Watch's equals() to use serialNumber field for comparison.
Then add constructor that accepts serialNumber.
public class Watch {
private final long serialNumber;
public Watch(long serialNumber) {
this.serialNumber = serialNumber;
}
#Override
public boolean equals(Object obj) {
return obj == this ||
(obj instanceof Watch && ((Watch)obj).serialNumber == serialNumber);
}
#Override
public int hashCode() {
return (int)serialNumber;
}
}
Replace if(watchStore.contains(s)){ with if(watchStore.contains(watchToFind)){ where Watch watchToFind = new Watch(s);
you can use contains method from org.apache.commons.lang.ArrayUtils package.
Checks if the value is in the given array.
The method returns false if a null array is passed in.
Parameters:
array the array to search through
valueToFind the value to find
Returns:
true if the array contains the object
long [] imageHashes= {12l,13l,14l,15l};
System.out.println(ArrayUtils.contains(imageHashes, 13l));

How to compare value of array of objects?

There is a collection of 20 objects of a POJO class. I Want to write a method that return objects with distinct value. Now this is my Pogo class
class Student {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName( String firstName ) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName( String lastName ) {
this.lastName = lastName;
}
}
Now i want some method which returns unique last names values. I could not understand which logic i have to put in this.
If you are using something like Eclipse, you can right-click the source and select Source > "Generate hashCode() and equals()...". Doing so will yield something like this:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
Then, you'll want to add your objects to an instance of Set, maybe HashSet. Sounds like you can just return the populated Set then.
See also this.
EDIT: Note that I am not suggesting to put all of this on the Student class. The code shown above goes on Student, but the method that returns the set of distinct students goes somewhere else.
EDIT 2: If you are only interested in unique last names, you could modify hashCode() and equals() to not consider first name, but I concede that this would be quite unintuitive and recommend to avoid this in any circumstance other than an academic exercise. So, more correct might be to layer on an instance of Comparator that only considers last name--see doc and this.
You can use an Arraylist, it has a built in function called .contains() which checks if the arrayList contains a specific value. So you would create an arrayList of last names and if it doesn't exist in the array list, just add it. See http://docs.oracle.com/javase/1.5.0/docs/api/java/util/ArrayList.html#contains(java.lang.Object)
You can try to use Set, if you need to get only one field, or Map, if you need to know object(student) with this field.
If you need to know all distinct Students (pair: first name + surname), you need to override getHashCode() and equals methods and use HashSet, HashMap
An easy way (for a beginner) to do this is just create a new array (same size of the input array). Then to loop through your array then compare every value to every other value in the array. If you can't find a match, then put this value in the new array.
Pseudo code:
public static Student[] GetUniqueLastNames(Student[] students){
Student[] retArray;//new array
for(i = 0; i < students.size; i++){
unique = true
for(j=0; j < students.size; j++){
if(i != j){//make sure its not comparing the same value
if(students[i].lastname.equals(students[j].lastname)){
unique = false
break
}
}
}
if(unique){
retArray[i] = students[i]
}
}
return retArray
}
Note: There are far better ways of doing this, but this is a nice basic way to do it if you're learning Java (or programming in general).
If you don't care about keeping the order of the objects, you can use a set:
public static <S extends Student> Collection<S> uniqByLastName(Collection<S> source){
TreeSet<S> result = new TreeSet<S>(new Comparator<S>() {
#Override
public int compare(S s1, S s2) {
return s1.getLastName().compareTo(s2.getLastName());
}
});
result.addAll(source);
return result;
}
If you care about the order
public static <S extends Student> Collection<S> uniqByLastName(Collection<S> source){
Collection<S> result = new ArrayList<S>();
Set<String> addedStudents = new HashSet<String>();
for(S student : source){
String lastName = student.getLastName();
if(!addedStudents.contains(lastName)){
result.add(student);
addedStudents.add(lastName);
}
}
return result;
}
If you want to modify the collection without returning a new one
public static <S extends Student> void uniqByLastName(Collection<S> source){
Set<String> addedStudents = new HashSet<String>();
Iterator<S> iterator = source.iterator();
while(iterator.hasNext()){
S student = iterator.next();
String lastName = student.getLastName();
if(addedStudents.contains(lastName)){
iterator.remove();
} else {
addedStudents.add(lastName);
}
}
}
If you are using Java 8, you can use lambda expression to solve it. Using following code snippet should solve your problem:
list.stream().collect(Collectors.toMap(Student::getLastName, p -> p, (p, q) -> p)).values();
Note: it will return first student with a given last name and as you might have already guessed, you don't need to override equals and hashcode.

May I get Null pointer exception from this routine?

I have written a below routine in Java, I need to know that the code is Null Pointer Safe or not:
public class TRM_Fields {
public static String returnActualValue(String Staffing_Event,
String CurrentValue, String PriorValue) {
String returnValue;
returnValue = null;
if ("TRM".equalsIgnoreCase(Staffing_Event) && CurrentValue == null
&& PriorValue != null && !"".equalsIgnoreCase(PriorValue)) {
returnValue = PriorValue;
} else {
returnValue = CurrentValue;
}
return returnValue;
}
}
Any of the parameter Staffing_Event, CurrentValue and PriorValue may be null.
If it is not Null Pointer Safe what should I do to achieve that?
Your method is safe. You are correctly using "constantString".equals(someObject) to ensure a null-safe comparison.
Some other comments:
Your method is hard to read because you are using TitleCase for Java variables, when they should be camelCase.
You only have two possible return values. So you can simplify your method as follows:
public static String returnActualValue(String staffingEvent,
String currentValue, String priorValue) {
if ("TRM".equalsIgnoreCase(staffingEvent) && currentValue == null
&& priorValue != null && !"".equalsIgnoreCase(priorValue)) {
return priorValue;
} else {
return currentValue;
}
}
Note that the else construct isn't necessary, so it's a matter of style whether you include that structure or simply have return currentValue;.

How do I make my string comparison case-insensitive?

I created a Java program to compare two strings:
String str = "Hello";
if (str.equals("hello")) {
System.out.println("match");
} else {
System.out.println("no match");
}
It's case-sensitive. How can I change it so that it's not?
The best way is to use str.equalsIgnoreCase("foo"). It's optimized specifically for this purpose.
You can also convert both strings to upper- or lowercase before comparing them with equals. This is a trick that's useful to remember for other languages which might not have an equivalent of equalsIgnoreCase.
str.toUpperCase().equals(str2.toUpperCase())
If you are using a non-Roman alphabet, take note of this part of the JavaDoc of equalsIgnoreCase which says
Note that this method does not take locale into account, and will
result in unsatisfactory results for certain locales. The Collator
class provides locale-sensitive comparison.
Use String.equalsIgnoreCase().
Use the Java API reference to find answers like these:
https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#equalsIgnoreCase(java.lang.String)
https://docs.oracle.com/javase/1.5.0/docs/api/
String.equalsIgnoreCase is the most practical choice for naive case-insensitive string comparison.
However, it is good to be aware that this method does neither do full case folding nor decomposition and so cannot perform caseless matching as specified in the Unicode standard. In fact, the JDK APIs do not provide access to information about case folding character data, so this job is best delegated to a tried and tested third-party library.
That library is ICU, and here is how one could implement a utility for case-insensitive string comparison:
import com.ibm.icu.text.Normalizer2;
// ...
public static boolean equalsIgnoreCase(CharSequence s, CharSequence t) {
Normalizer2 normalizer = Normalizer2.getNFKCCasefoldInstance();
return normalizer.normalize(s).equals(normalizer.normalize(t));
}
String brook = "flu\u0308ßchen";
String BROOK = "FLÜSSCHEN";
assert equalsIgnoreCase(brook, BROOK);
Naive comparison with String.equalsIgnoreCase, or String.equals on upper- or lowercased strings will fail even this simple test.
(Do note though that the predefined case folding flavour getNFKCCasefoldInstance is locale-independent; for Turkish locales a little more work involving UCharacter.foldCase may be necessary.)
You have to use the compareToIgnoreCase method of the String object.
int compareValue = str1.compareToIgnoreCase(str2);
if (compareValue == 0) it means str1 equals str2.
import java.lang.String; //contains equalsIgnoreCase()
/*
*
*/
String s1 = "Hello";
String s2 = "hello";
if (s1.equalsIgnoreCase(s2)) {
System.out.println("hai");
} else {
System.out.println("welcome");
}
Now it will output : hai
In the default Java API you have:
String.CASE_INSENSITIVE_ORDER
So you do not need to rewrite a comparator if you were to use strings with Sorted data structures.
String s = "some text here";
s.equalsIgnoreCase("Some text here");
Is what you want for pure equality checks in your own code.
Just to further informations about anything pertaining to equality of Strings in Java. The hashCode() function of the java.lang.String class "is case sensitive":
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
So if you want to use an Hashtable/HashMap with Strings as keys, and have keys like "SomeKey", "SOMEKEY" and "somekey" be seen as equal, then you will have to wrap your string in another class (you cannot extend String since it is a final class). For example :
private static class HashWrap {
private final String value;
private final int hash;
public String get() {
return value;
}
private HashWrap(String value) {
this.value = value;
String lc = value.toLowerCase();
this.hash = lc.hashCode();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof HashWrap) {
HashWrap that = (HashWrap) o;
return value.equalsIgnoreCase(that.value);
} else {
return false;
}
}
#Override
public int hashCode() {
return this.hash;
}
}
and then use it as such:
HashMap<HashWrap, Object> map = new HashMap<HashWrap, Object>();
Note that you may want to do null checks on them as well prior to doing your .equals or .equalsIgnoreCase.
A null String object can not call an equals method.
ie:
public boolean areStringsSame(String str1, String str2)
{
if (str1 == null && str2 == null)
return true;
if (str1 == null || str2 == null)
return false;
return str1.equalsIgnoreCase(str2);
}
Use s1.equalsIgnoreCase(s2): https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#equalsIgnoreCase(java.lang.String).
You can use equalsIgnoreCase
More about string can be found in String Class and String Tutorials
To be nullsafe, you can use
org.apache.commons.lang.StringUtils.equalsIgnoreCase(String, String)
or
org.apache.commons.lang3.StringUtils.equalsIgnoreCase(CharSequence, CharSequence)
public boolean newEquals(String str1, String str2)
{
int len = str1.length();
int len1 = str2.length();
if(len==len1)
{
for(int i=0,j=0;i<str1.length();i++,j++)
{
if(str1.charAt(i)!=str2.charAt(j))
return false;
}`enter code here`
}
return true;
}

Categories

Resources