Conversion of Vector<Vector> to a String Array or a String[][]

110 Views Asked by At

I have a JTable containing only one columns of , called "Points" Points

I have another JTable containing seven columns of , called "Lines" Lines

I am writing a button handler that removes every point (row) in Points which is not found in Lines as it is not utilized.

I extract the content of Points one point (row) at a time. I extract the entire content of Lines ideally in a String Array. Unluckily the method I use with Lines outputs a Vector. I cannot find a way to convert from Vector to String Array or similar data type. My goal is to search in Lines for the single point from Points without using nested loops. I tried the following instructions but they do not work. Presumably because the method "contains()" does not work when searching a Vector. I would greatly appreciate some suggestion. Thank you in advance.

I tried the following:

        btnDeleteUnused.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
               Vector<Vector> data =  linesTableModel.getDataVector();
                for(int k = pointsTableModel.getRowCount() - 1; k >= 0; k--)
                {
                     String pn = (String) pointsTableModel.getValueAt(k, 0);    // Fetch Point Name at (k_th row, column 0)
                     System.out.println("Current Point:  "+ pn);
                     System.out.println(data.contains(pn));
                }
                // TO BE DEVELOPED 
            }
        });
2

There are 2 best solutions below

15
Old Dog Programmer On

You do indeed have a problem with using contains on your data Object. It results because you are attempting to search for, presumably, a String, but each element of data is not a String. Each element is another Vector. The data variable is essentially a 2D Vector. Thus, data.contains(pn) is searching for a String that is the same as a row of Vectors, so will always return false.

An analogy: Think of data as a case. The case contains some number of boxes of candy. But, the lists of types of candy is missing. You want to find whether or not the case contains any caramel candy. The code in the question using data.contains(pn) is like going through the case, picking out one-box-at-a-time, and asking "Is this box a piece of caramel?" To find out if the case contains any caramel candy, you want to open each box, and then check each piece in that box.

To access a single element of a Vector<Vector>, you need to use two indexes. See the example in the API.

So, to search for a specific String, you need to search element-by-element with nested loops, or use contains within a loop.

The following method can be used to find the first location of an occurrence of a target String. This uses the contains method within a loop. It returns an int [] with two elements: One for the outer index, the other for the inner index:

public static int [] indexOf (Vector<Vector> theVector, String target) {
    for (int outer = 0; outer < theVector.size (); outer++) { 
        int inner = theVector.get(outer).indexOf (target);
        if (inner >= 0) { 
            return new int [] {outer, inner};
        }
    }
    return new int [] { -1, -1};
}

Following is a refactored indexOf (Vector<Vector> theVector, String target) method. Instead of using contains, the code shows how each element might be accessed. The code uses some intermediate variables, which should make it easier to follow.

It also fixes another issue, which is explained after the code sample:

public static int [] indexOf (Vector<Vector> vectorVector, String target) {
    for (int outer = 0; outer < vectorVector.size (); outer++) { 
        Vector rowVect = vectorVector.get(outer);
        for (int inner = 0; inner < rowVect.size(); inner++) {
            Object obj = rowVect.get(inner);
            if (obj.toString().equalsIgnoreCase (target)) {
                return new int [] { outer, inner};
            }
        }
    }
    return new int [] { -1, -1};
}

The other issues is this:

An element of JTable does not necessarily have to be a String. So, it isn't necessarily the case that each element of data is a String. An element of data might be, hypothetically, a Foo. Suppose your code is looking for an element of data that corresponds to "Eleven". It so happens, the Eleven is actually associated with the Foo, because its toString() method returns "Eleven". The first version won't work. The refactored version solves this by using String#equals method.

Note that the refactored version actually uses .equalsIgnoreCase to illustrate the revision makes that possible.

Your code has

System.out.println(data.contains(pn));.

You could use the above method by changing that line to

System.out.println(indexOf (data, pn)[0] != -1);

When you develop more code, you could access the specific element like this:

int [] location = indexOf (data, pn);
if (location [0] >= 0) {
    String foo = data.get(location[0]).get(location[1]);
    ...
0
Old Dog Programmer On

In my other answer, I tried to explain how to search for a specific String value in the data variable in Vector<Vector> data = linesTableModel.getDataVector(); I took that to be what you actually asking. This answer, instead, addresses the question header, and ignores the question body.

Keeping in mind that data is a Vector in which each element is another Vector, you can convert its contents to a 2D array using nested loops. Here is code for such a method:

public static String [][] VectorToString2D (Vector<Vector> vect) { 
    String [][] result = new String [vect.size()][];
    for (int rowIndex = 0; rowIndex < vect.size(); rowIndex++) {
        Vector vectRow = vect.get(rowIndex);
        String [] stringRow = new String [vectRow.size()];
        for (int columnIndex = 0; columnIndex < vectRow.size(); columnIndex++) {
            stringRow [columnIndex] = vectRow.get(columnIndex).toString();
        }
        result [rowIndex] = stringRow;
    }        
    return result;
}

As in the previous answer, this uses toString to allow for the possibility that elements in data are not necessarily String Objects.