How to check following object is blank or not? I have below class and how could I check that my sample class has nothing data without checking every member of it?
public class Test {
public static void main(String[] args){
Sample sample = new Sample();
if(sample!=null){
System.out.println("Object is blank..");
}
}
}
class Sample {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
First you need to define what "blank" means in business terms. What exactly is a "blank" object? Is it an object with a null name? With an empty string name? With some other combination of empty parameters?
Once you've defined what a "blank" object actually is, I recommend adding a method to perform that logic based on the object's current contents and return the results:
public boolean isBlank () {
return ...; // whatever "blank" means
}
If possible I advise against using a flag-based approach. While there are certainly valid reasons for it, adding a flag means your setters must maintain the correct value of the flag at all times (and you must also update it after deserialization).
I am assuming that by emptiness of object, you mean that the instance variables are not initialized. I don't think there is any available method to check such emptiness of an object.
If you have to do this, then you may need to write your own method checking the fileds. You should check for the default values of the primitives and null check for object types. An example of such a method for your class is:
public boolean isEmpty() {
if(this.id == 0 && this.name == null)
return true;
else
return false;
}
Please don't consider this as the perfect implementation, so customize as per your need.
One option to create a boolean flag and manipulate it in setters.
Make a private isBlank:
private boolean isBlank=true;
then have setters call isBlank=false. Any setter calls will make the object not blank. Then add a getter checkIsBlank( that returns isBlank.
Note that the setters should detect a set to null. In that case, they'll need to check all fields. This is left as an exercise to the reader.
What I would do, provide a constructor that takes id and name, therefore you know the object will never be blank:
public class Sample{
private int id;
private String name;
public Sample(int id, String name){
this.id = id;
this.name = name;
}
}
A hack that you could do with your current class is override the toString method:
class Sample {
private int id;
private String name;
#Override
public String toString(){
try{
return Integer.toString(id) + name;
} catch(Execption e){
return "";
}
}
}
if(sample.toString().isEmpty())
System.out.println("Object is blank");
You could check if the object is blank by either comparing it to a newly-instantiated object.
public boolean isBlank() {
return this.equals(new Sample());
}
#Override
public boolean equals(Object o) {
boolean toRet;
if(o == null || !o instanceof Sample) {
toRet = false;
}
else {
Sample b = (Sample) o;
toRet = this.id == b.id
&& (this.name == null ? b.name == null : this.name.equals(b.name));
}
return toRet;
}
Old answer: What you can do is create a modified boolean, which is initialized as false, then set to true any time a setter is called.
class Sample {
public static final int INVALID_ID = -1;
private int id = Sample.INVALID_ID;
private String name = null;
private boolean modified = false;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
modified = true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
modified = true;
}
public boolean isModified() {
return modified;
}
}
Related
How do I check if an element exists in a queue ( LinkedList ) before adding it ?
EX:
Address [id=1, url=https://www.google.com, size=2, queue=[request [requestId=1], request [requestId=2]]]
I can't add queue=[request [requestId=1], request [requestId=1]] because they have the same requestId.
you can use contains(Object o) method
contains description:
Returns true if this list contains the specified element. More
formally, returns true if and only if this list contains at least one
element e such that (o==null ? e==null : o.equals(e)).
[...]
Parameters: o –
element whose presence in this list is to be tested
Returns: true if
this list contains the specified element
LinkedList implements the Collection interface, which defines the Collection#contains method.
You can do what you're after with any class that derives from Collection easily by just using the contains method.
See the docs on LinkedList#contains for more information.
Note: It uses Objects#equals to determine if the item is in the Collection.
If you have the same reference, I think you'll be good. If you have different references representing the same data, then you may need to #Override the equals method on your object.
Below code may help you...
package com.example.Solution;
import java.util.LinkedList;
import java.util.Queue;
public class Sol {
public static void main(String[] args){
Queue<Address> q1= new LinkedList<>();
q1.add(new Address("abc",1,"url1"));
Address a1=new Address("abc",1,"url");
if(!q1.contains(a1))
q1.add(a1);
Address a2=new Address("abc",2,"url");
if(!q1.contains(a2)){
q1.add(a2);
}
Address a3=new Address("abc",1,"url2");
if(!q1.contains(a3)){
q1.add(a3);
}
System.out.println(q1.size());
}
}
class Address {
String name;
int id;
String url;
public Address(String name, int id, String url) {
this.name = name;
this.id = id;
this.url = url;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public boolean equals(Object o1){
Address address=(Address) o1;
return address.getId()==this.id;
}
}
I have an below object
class CustomObj{
private String name;
private String dept;
public String getName(){
return this.name;
}
public String getDept(){
return this.dept;
}
private CustomObj(){
}
private CustomObj(CustomObjBuilder builder){
this.name = builder.name;
this.dept= builder.dept;
}
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (o == null || getClass() != o.getClass()) return false;
CustomObj that = (CustomObj) o;
return that.name.equals(name) &&
that.dept.equals(dept);
}
#Override
public int hashCode() {
int result = 31;
result = 31 * result + name.hashCode();
result = 31 * result + dept.hashCode();
return result;
}
public static class CustomObjBuilder{
private String name;
private String dept;
public CustomObjBuilder(String name, String dept){
this.name = name;
this.dept = dept;
}
public CustomObjBuilder setName(String name){
this.name = name;
return this;
}
public CustomObjBuilder setDept(String dept){
this.dept = dept;
return this;
}
public CustomObj build(){
return new CustomObj(this);
}
}
}
and class that uses above
class XYZ{
Set<CustomObj> obj = new HashSet<CustomObj>();
public void process(String a, String b){
CustomObj o = new CustomObj.CustomObjBuilder(a,b).build();
if(!obj.contains(o)){
obj.add(o);
}
}
}
And a test class
class TestXYX{
#Test
public void test(){
XYZ xyz = new XYZ();
xyz.process("TEST","TESTABC");
xyz.process("TEST","TESTABC");
}
}
Beacuse I have overrideen hascode and equals, both the above are equal and when process is called second time, the control should not go into if(!obj.contains(o)) second time and size of the set should be 1. But when i run the test obj.add(o); is called two times. But the values of both this object and that objec inside equals methods are same, but
that.name.equals(name) && that.dept.equals(dept)
inside CustomObj returns false. Can someone please help me understand why?
The code is fine. To verify add an sysout to check Set size:
class XYZ {
Set<CustomObj> obj = new HashSet<CustomObj>();
public void process(String a, String b) {
CustomObj o = new CustomObj.CustomObjBuilder(a, b).build();
if (!obj.contains(o)) { // Fails second time for your use case.
obj.add(o);
}
System.out.println(obj.size()); // This is 1 in your use case.
}
}
This question already has answers here:
Setting own class as key in java Hashmap
(7 answers)
Closed 6 years ago.
lets say I have a Employee-class with Instant- and Id-Attribute:
public class Employee implements Comparable<Employee> {
private Instant workEnd;
private Integer id;
private String name;
public Instant getWorkEnd() {
return workEnd;
}
public void setWorkEnd(Instant workEnd) {
this.workEnd = workEnd;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public int compareTo(Employee employee) {
int workEndCompare = getWorkEnd().compareTo(employee.getWorkEnd());
int idCompare = getId().compareTo(employee.getId());
if (workEndCompare == 0) {
return idCompare;
} else {
return workEndCompare;
}
}
#Override
public String toString() {
return String.format("{Date: %s,Number: %d}", getWorkEnd(), getId());
}
}
As you can see each Employee-Object sorts dependent on workEnd and id.
Now I want to put these Employee-Objects as Keys in a HashMap. But I want that the HashMap replaces each Key-Employee with the put()-method if the attributes workend and id are equal. Thta means I want the normal behaviour of a HashMap but with own custom Objects as Mapkeys.
How I manage that? By implementing the equals-method?
I tried something like that, but it does not work:
#Override
public boolean equals(Object obj) {
if (obj instanceof Employee) {
Employee employee = (Employee) obj;
int workEndCompare = getWorkEnd().compareTo(employee.getWorkEnd());
int idCompare = getId().compareTo(employee.getId());
if ((idCompare + workEndCompare) == 0) {
return true;
} else {
return false;
}
} else {
return super.equals(obj);
}
}
When you implement the equals method you also need to implement the hashcode method too.
There is something called the hashcode - equals contract, both need to be implemented for your hashmap to work,
The answer here explains it well.
I am learning about immutable Objects. I am trying this code
public final class ImmutableObject {
private final String name;
private final NormalObject obj = new NormalObject();
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
obj.setName(name);
}
public NormalObject getObj() {
NormalObject tempObj = obj;
return tempObj;
}
}
public class NormalObject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I want to restrict the calling class from changing the value of name variable of NormalObject
But the following code changes the value
ImmutableObject obj = new ImmutableObject("Siddle");
System.out.println(obj.getObj().getName()); //prints Siddle
obj.getObj().setName("Kelly");
System.out.println(obj.getObj().getName()); //prints Kelly
How to restrict it?
For an object to be immutable, all of its properties must be immutable. Its state must not be changeable.
To do that, you have to put an immutable facade on NormalObject, you can't directly return a NormalObject. The method that returns it will also need a different return type, you can't return NormalObject but actually return something that doesn't behave like a NormalObject.
E.g.:
public final class ImmutableObject {
private final String name;
private final NormalObject obj = new NormalObject();
private final ImmutableNormalObject objFacade = new ImmutableNormalObject(obj);
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
obj.setName(name);
}
public ImmutableNormalObject getObj() {
return objFacade;
}
}
public class NormalObject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class ImmutableNormalObject {
private NormalObject obj;
public ImmutableNormalObject(Normalobject o) {
this.obj = o;
}
public String getName() {
return obj.getName();
}
}
Alternately, if it's acceptable to copy the object and it has a copy constructor (or you can add one), you could do that, but copy-and-return is expensive.
You can do this by returning a copy of your normalObject in getter:
public NormalObject getObj() {
return new NormalObject(obj.getName());
// or you can make a copy constructor:
// return new NormalObject(obj);
}
Or you can make a wrapper for your NormalObject that ignores name setter, but it brakes logic.
Please change Your NormalObject code to
public final class ImmutableObject {
private final String name;
// initialise it to null
private final NormalObject obj = null;
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
// use the Constructor for setting name only once during initialization of ImmutableObject via its constructor
obj = new NormalObject(name);
//obj.setName(name);
}
public NormalObject getObj() {
NormalObject tempObj = obj;
return tempObj;
}
}
NormalObject Class
public class NormalObject {
private String name;
public NormalObject(name){
this.name = name;
}
public String getName() {
return name;
}
//Remove any setter on NormalObject
/*public void setName(String name) {
this.name = name;
}*/
}
In an immutable object, if a User tries to change the state of the Object. either you won't allow or return a new Instance of the Immutable class.
So, since Date is a mutable class.
You can create an immutable wrapper around date, and you can expose only those methods, that are subject to be used in your Immutable-Date's perspective, but you return a new instance of your Immutable class, with the changed attribute of your new Date.
I don't think final would be required for Immutable variable, because it is already private and Immutable.
Example :
public class Main{
private ImmutableDate immutableDate;
public Main() {
this.immutableDate = new ImmutableDate(new Date());
}
public Main(Date date){
this.immutableDate = new ImmutableDate(date);
}
public ImmutableDate getDate() {
return immutableDate;
}
public class ImmutableDate{
// private constructor, so this can only be instantiated within the outer class
// therefore, final keyword not required for Date, as no access given to the variable
private Date date;
private ImmutableDate(Date date) {
this.date = date;
}
// Example methods from Date, that are required for our Immutable implementation
public Main setTime(long time){
Date date1 = new Date();
date1.setTime(time);
return new Main(date1);
}
#Override
public String toString() {
return date.toString();
}
}
}
public class People {
// Code to create a random set of people omitted
public Set getAllPeople() {
return people;
}
public void setPerson(Person person) {
if (person.getId() == -1) {
person.setId(getNextId());
}
people.remove(person);
people.add(person);
}
public void deletePerson(Person person) {
people.remove(person);
}
private Set people = new HashSet();
}
public class Person
{
private int id;
private String name;
private String address;
private float salary;
// Getters, setters, equals and toString omitted
}
While looking after the DWR website i found this example.It states that they omitted Getters, setters, equals and toString. How to write those for this program. I wish to run this program and see. Any Suggestions Please. Help out..
Getters and Setters are used to retrieve your "private" variables ( = variables visible inside the class they are defined only), from outside the class.
For instance:
private String name;
would have a getter like this:
public String getName() {
return name;
}
And a setter like this:
public void setName(String name) {
this.name = name;
}
(you could use "protected" if you only wanted this variable to be visible in the package, and not in the whole project).
the toString() method is here if you want to display some information about your object, which might be useful from a debugging point of view.
The equals method would be used to know how you want to compare to objects of Person type (by ids only for instance).
Have a look at this link to have more info on what is equals.
As RonK suggested, be sure to implement hashCode if you do implement equals, they go together, and have to use the same fields (part of the contract).
The rule is that if:
objectA.equals(objectB) returns true
then
objectA.hashCode() has to be equal to objectB.hashCode()
for each property in Person class you need to define 2 methods
for example id:
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
and you need to override equals and hashcode method to put your own condition for equality
public boolean equals(Object that) {
if (that == null) {
return false;
}
if (!(that instanceof Person)) {
return false;
}
return this.id == ((Person) that).id;
}
public int hashCode() {
return id * 17;
}
public class Person
{
//Id should be unique
private int id;
private String name;
private String address;
private float salary;
public Person(int id, String name, String address, float salary)
{
this.id = id;
this.name = name; //Maybe check for null
this.address = address; //Maybe check for null
this.salary = salary; //Maybe check for > 0
}
public int getId()
{
return id;
}
//No setID() - do you want that? you properly shouldn't
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address; //Maybe check for null
}
public float getSalary()
{
return salary;
}
public setSalary(float salary)
{
this.salary = salary;
}
//A person is equal if they have the same ID
#Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Person person = (Person)obj;
return person.id == id;
}
#Override
public int hashCode()
{
return id;
}
//Just returns the name but you could return more details
#Override
public String toString()
{
return name;
}
}
Added hashCode which is essential - especially if you use it in a HashSet.