Archive

Posts Tagged ‘vectors’

Refactoring simple code

September 25, 2009 Leave a comment

In this essay I’ll be outlining and exposing some of the approaches, thought processes & strategies I engage in when refactoring code. I’ll continue with some of the very simple themes outlined in Fun with String vectors… Part 1.Let’s say we now want to add two String vectors (usually derived from String arrays) together…. It’s something I often have to do when handling blocks of multiline text…

public  Vector<String> joinVectors(Vector<String> v1, Vector<String> v2)
{
Vector<String> vOutput = getPreparedVector();
vOutput.addAll(v1);
vOutput.addAll(v2);
return vOutput;
}

Easy enough. But I think you’ll agree that a lot of this vector activity is more geared to action surrounding the vector or array being handled than the String replacement class and probably really belongs in a class of its own. So at this point we might seriously think about refactoring and moving the Vector action to a StringVector class. The upshot of this is that we might also want to do similar sorts of things for all the other collection classes which we might be using to operate on Strings with. It also occurs to me that a lot of this sort of activity is not only pertinent to Strings but might equally well apply to Integers and all other non-primitive types which we might want to work on, e.g. Integers, Longs, etc. We will probably want to supply an interface to ensure conformity across our proposed StringVector class and, say, an IntegerVector class or a LongVector class.

The first and immediately obvious candidate for refactoring from previously is the method with the signature public Vector getPreparedVector(), a neutral enough name.

The next is the vectorToStringArray( Vector v ) , however it might appear as if semantics is going to be an issue here because we will want this method signature’s name to be applicable to all the other Objects we may need classes for (e.g. we are going to be deeply confused calling IntegerVector.vectorToStringArray()), so first off we could neutralise this by renaming it to vectorToArray. However, it should be apparent to you that vectorToArray(Vector v) is less a function of a Collection class than a generic Array replacement class, which we might putatively name ArrayMaster, where it will live with similar methods which will produce different types of arrays… for example an Integer array. In an ideal world this would present no problem but of course Java doesn’t recognise overloading on return values and two identically named methods will result in Java or your IDE notifying you that the overloaded method with the different return signature is already defined in the class. So.. The simple thing is to have one uniquely named method per Object type, i.e. vectorToIntegerArray, vectorToLongArray etc.

The other thing we might have liked to consider is to produce a method with the signature public Object[] vectorToArray(Vector v). However this won’t fly since you can’t cast a Java supertype Array into a subtype, and if you attempt to compile it you would get a ClassCastException, the reason being that every element would need to be examined by the JVM for type safety. (The rules for this can be found here: http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#20232). So it’s back to the drawing board with discretely named methods vectorToStringArray, vectorToIntegerArray, vectorToLongArray etc.

We can however make these Array conversion utilities simpler by refactoring the code a tad and taking advantage of Vector’s toArray() method e.g. from :

/**
* Will convert a passed vector to a string array
* @param Vector v - the vector for conversion
* @return String array of the converted vector
*/
public String[] vectorToStringArray( Vector<String> v )
{
int count = v.size();
String[] outArray = new String[count];
v.copyInto(outArray);
return outArray;
}

to:

/**
* Will convert a passed vector to a string array
* @param Vector v - the vector for conversion
* @return String array of the converted vector
*/
public String[] vectorToStringArray(Vector<String> v)
{
return (String[])v.toArray(new String[v.size()]);
}
// and our new Integer component.....
/**
* Will convert a passed vector to a integer array
* @param Vector v - the vector for conversion
* @return Integer array of the converted vector
*/
public Integer[] vectorToIntegerArray(Vector<Integer> v)
{
return (Integer[])v.toArray(new Integer[v.size()]);
}

[..]

Next up we can look at public Vector getVectorFromStringArray(String[] inArray) . The name is frankly horrible and we immediately refactor this to vectorToArray. While this is ostensibly type-agnostic, we will however want to type-check the Vector per Object type, and add one implementation per ObjectVector class, i.e. there will be a method typechecking and producing String Vectors in StringVector, Integers in IntegerVector, etc.

So we now have two obvious methods to define in our proposed vectorInterface interface, getPreparedVector and arrayToVector, which should look something like this.

import java.util.Vector;

public interface VectorInterface {
    public Vector getPreparedVector();
    public Vector arrayToVector(Object[] xArray);
}

Our new StringVector class should look something like this (I’ve removed comments, etc, for concision):

import java.util.Vector;

public class StringVector implements VectorInterface {

public  Vector<String> getPreparedVector()
{
Vector<String> vOutput = new Vector<String>();
return vOutput;
}

public  Vector<String> arrayToVector(Object[] sArray)
{
Vector<String> v = getPreparedVector();
for (int i = 0; i<sArray.length; i++)
{
v.add(sArray[i].toString());
}
return v;
}
/* Method to join two String vectors
* @param v1 vector to add to
* @param v2 vector to be added on to v1
* @return the joined vectors
*/
public  Vector<String> joinVectors(Vector<String> v1, Vector<String> v2)
{
Vector<String> vOutput = getPreparedVector();
vOutput.addAll(v1);
vOutput.addAll(v2);
return vOutput;
}

}

And our IntegerVector class will look pretty much the same with Integer substituted for String appropriately,and an Integer conversion of

v.add(sArray[i].toString()); 

to read

v.add(Integer.parseInt(sArray[i].toString()));
//or (if we can be sure of the contents of the Array)
v.add((Integer) sArray[i]);

Fun with String vectors… Part 1

September 13, 2009 Leave a comment

Working extensively with Strings inevitably entails working with arrays. Lots of them. In this article I will be looking at how some of the pain can be taking out of this in our putative replacement class for String.

First off, one thing which makes working with String arrays easier is to convert your array to a Vector, ArrayList or one of the other Collection classes; your mileage will vary based around a number of criteria, not the least being what you intend to do, whether you need to handle this in a threaded manner, etc, etc and due consideration of the right Collection class to utilise is important; I have opted for Vector for this illustration because it has broadly based utility.

Arrays inherently are messy to work with and serial abuse of them inevitably results in an unhealthy proliferation of for loops, often nested to the point of Lovecraftian insanity.

Let’s therefore pretend for the purposes of simplicity & clarity in this article that we only have the Vector class with which to work. First off we’ll need to add

import java.util.Vector;

to our class header.

On demand empty String Vector

Next we’ll need a method to create an instant on-demand String Vector method:

public  Vector<String> getPreparedVector()
{
Vector<String> vOutput = new Vector<String>();
return vOutput;
}

Converting String[] to a Vector

Next up we need to have a method to pass a String array to a Vector since most of the inbuilt String class methods we frequently need recourse to produce output as an array. This we can do as follows:

/*
* @param inArray - the array to convert to a Vector
* @return the populated Vector from incoming String array
*/
public  Vector getVectorFromStringArray(String[] inArray)
{
// since this will be the same length as s but parsed
Vector<String> v = getPreparedVector();
for (int i = 0; i < inArray.length; i++)
{
v.add(inArray&#91;i&#93;);
}
return v;
}&#91;/sourcecode&#93;

<strong>Vector to String[]</strong>

And of course we will likely need a method to reverse the process, i.e. to convert the Vector back to an array...

/**
* Will convert a passed vector to a string array  
* @param Vector v - the vector for conversion
* @return String array of the converted vector
*/
public String[] vectorToStringArray( Vector v )
{
int count = v.size();
String[] outArray = new String[count];
v.copyInto(outArray);
return outArray;
}

Vector is responsible for very little of the code in the above method, and you are probably seeing already why it is a better candidate for hardcore work than an array: it has functionality which obviates the need for intricate loops. Most of the effort here derives from having to accomodate the somewhat Byzantine complexities of the Array class.

Growing a vector

One immediate advantage which a Vector has over an array is that the number of elements which it contains can be increased or decreased dynamically. The API documentation for Vector makes this point explicitly:

The Vector class implements a growable array of objects. Like an array, it contains components that can be accessed using an integer index. However, the size of a Vector can grow or shrink as needed to accommodate adding and removing items after the Vector has been created.

Each vector tries to optimize storage management by maintaining a capacity and a capacityIncrement. The capacity is always at least as large as the vector size; it is usually larger because as components are added to the vector, the vector’s storage increases in chunks the size of capacityIncrement. An application can increase the capacity of a vector before inserting a large number of components; this reduces the amount of incremental reallocation.

Inevitably, we will want to add and remove elements from our Vector; a royal pain with an Array, but a moment’s work in a Vector…

Vector<String> v = getPreparedVector();
v.add("Hello");
v.add("World");
v.add("A superfluous element");
v.add("etc");
v.remove(3);

[..]