Skip to content
Advertisement

How to implement an increment method on pairs

I am working on a circular linked list and have implemented the following method to increment the elements of the list by a given value.

 public void IncrementList(E e) {
    if (!isEmpty()) {
        Node<E> temp = current;

        do {
            Double res = temp.element.doubleValue() +  e.doubleValue();
            temp.element = (E) res;
            temp = temp.next;
        } while (temp != current);
    }
}

This method works fine with lists of doubles; however, now I am trying to use it on a list of pairs but I keep getting an error since the method is used for doubles. What should I do to change this method and let it accept pairs and increment them. The following is the pair class I implemented:

public class Pair implements Comparable<Pair> {
    int x, y;
    
    public Pair(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int getX() {
        return x;
    }
    
    public void setX(int x) {
        this.x = x;
    }
    
    public int getY() {
        return y;
    }
    
    public void setY(int y) {
        this.y = y;
    }
    
    public String toString() {
        return "(" + x + "," + y + ")";
    }
    
    @Override
    public int compareTo(Pair o) {
    if (this.x > o.x)
        return 1;
    if (this.x < o.x)
        return -1;
    else 
        return 0;
    }
}

Advertisement

Answer

You could introduce an interface Incrementable like this one:

/**
 * Interface for objects that can be "incremented" by values 
 * from another object
 * @param <E>   element type
 */
public interface Incrementable<E> {
    public E incrementBy(E otherObj);
}

When implementing this interface in Pair the method can be specified as

@Override
public Pair incrementBy(Pair otherObj) {
    if (otherObj == null) {
        return new Pair(this.getX(), this.getY());
    }
    return new Pair(this.getX() + otherObj.getX(), this.getY() + otherObj.getY());
}

Please note that the IncrementList(E) method also needs to be changed:

public void IncrementList(E e) {
    if (!isEmpty()) {
        Node<E> temp = current;
        do {
            E increasedValue = temp.element;
            if ((e instanceof Incrementable) && (temp.element instanceof Incrementable)) {
                increasedValue = ((Incrementable<E>)temp.element).incrementBy((E)(Incrementable<E>)e);
            } else {
                // perform increment on other types?
                //increasedValue = IncrementUtils.increment(temp.element, e);
            }
            if (increasedValue != null) {
                temp.element = increasedValue;
            }
            temp = temp.next;
        } while (temp != current);
    }
}

One additional point to consider: should the interface Incrementable return new instances of the same type but with values increased (like BigInteger.add(BigInteger) does) or should the method work with the values in the object itself (like StringBuilder.add(...) does)? It depends on your overall use cases which way to specify this behavior.

The code above assumes that new instances will be used; if you prefer to change the values inside the objects, then the signature in the interface should be void incrementBy(E) and the IncrementList(E) method does not need to re-assign the increased value after applying the increase.

One last thought: to make the IncrementList(E) method work with elements that do not implement Incrementable you can use a helper class with a method that handles some other types of objects, especially Numbers and Strings. As this classes do not support changing their “internal” values, you need to re-assign the result of the increase call to the list elements.

As a starting point, this helper class could look like this:

public class IncrementUtils {
    
    public static <E> E increment(E obj1, E obj2) {
        if ((obj1 == null) || (obj2 == null)) {
            return null;
        }
        if ((obj1 instanceof Integer) && (obj2 instanceof Integer)) {
            return (E)(Integer)(((Integer)obj1) + ((Integer)obj2));
        }
        if ((obj1 instanceof Double) && (obj2 instanceof Double)) {
            return (E)(Double)(((Double)obj1) + ((Double)obj2));
        }
        if ((obj1 instanceof Long) && (obj2 instanceof Long)) {
            return (E)(Long)(((Long)obj1) + ((Long)obj2));
        }
        if ((obj1 instanceof Float) && (obj2 instanceof Float)) {
            return (E)(Float)(((Float)obj1) + ((Float)obj2));
        }
        if ((obj1 instanceof BigDecimal) && (obj2 instanceof BigDecimal)) {
            return (E)((BigDecimal)obj1).add((BigDecimal)obj2);
        }
        if ((obj1 instanceof BigInteger) && (obj2 instanceof BigInteger)) {
            return (E)((BigInteger)obj1).add((BigInteger)obj2);
        }
        if ((obj1 instanceof String) && (obj2 instanceof String)) {
            return (E)((String)obj1 + (String)obj2);
        }
        if ((obj1 instanceof StringBuilder) && (obj2 instanceof StringBuilder)) {
            return (E)(new StringBuilder().append(obj1).append(obj2));
        }
        if ((obj1 instanceof StringBuffer) && (obj2 instanceof StringBuffer)) {
            return (E)(new StringBuffer().append(obj1).append(obj2));
        }
        return null;
    }
    
}
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement