I have an arrayList that contains arrays. How do I check if the arrayList contains a specified array? I used .contains method and it returns false instead of expected true.
import java.util.ArrayList;
import java.util.Arrays;
public class main {
public static void main(String[] args) {
ArrayList<String[]> action = new ArrayList<String[]>();
action.add(new String[]{"appple", "ball"});
String[] items = new String[]{"appple", "ball"};
if (action.contains(new String[]{"appple", "ball"})) {
System.out.println("Yes");
}
System.out.println(action.contains(items)); // False
}
}
As you are creating different arrays (even if the contents are the same), contains will result false.
However, if you do this:
List<String[]> action = new ArrayList<String[]>();
String[] items = new String[]{"apple","ball"};
action.add(items);
if (action.contains(items))
System.out.println("Yes");
This will print Yes.
Also, some examples of the behaviour:
String[] items = new String[]{"apple","ball"};
action.add(items);
String[] clone = items.clone();
String[] mirror = items;
action.contains(clone); // false
action.contains(mirror); // true
items[0]="horse";
System.out.println(mirror[0]); // "horse"
System.out.println(clone[0]); // "apple"
System.out.println(action.get(0)[0]); // "horse"
mirror[1]="crazy";
System.out.println(clone[1]); // "ball"
System.out.println(action.get(0)[1]); // "crazy"
System.out.println(items[1]); // "crazy"
clone[1]="yolo";
System.out.println(action.get(0)[1]); // "crazy"
System.out.println(items[1]); // "crazy"
System.out.println(mirror[1]); // "crazy"
System.out.println(action.get(0).hashCode()); //2018699554
System.out.println(items.hashCode()); //2018699554
System.out.println(clone.hashCode()); //1311053135
System.out.println(mirror.hashCode()); //2018699554
Custom "contains"
The issue here is that if you want to search for an specific array afterwards, you'd lose the references and searching an item wouldn't be possible, not even replicating the array with the same exact values.
As a workaround, you could implement your own contains method. Something like:
If you wish to get the index:
static int indexOfArray(List<String[]> list, String[] twin)
{
for (int i=0;i<list.size();i++)
if (Arrays.equals(list.get(i),twin))
return i;
return -1;
}
And then, call it like:
String[] toSearch = new String[]{"apple","ball"};
int index = indexOfArray(action, toSearch);
if (index>0)
System.out.println("Array found at index "+index);
else
System.out.println("Array not found");
If the index is bigger than -1, you can get your original array by just:
String[] myArray = action.get(index);
HashMap + identifier
An alternative would be storing the arrays into a HashMap by declaring an identifier for each array. For example:
Base64 ID
This will give the same result for the same values, as the encoded value is based on the entries, not the Object's reference.
static String getIdentifier(String[] array)
{
String all="";
for (String s : array)
all+=s;
return Base64.getEncoder().encodeToString(all.getBytes());
}
And then you could:
Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"}; // *[1234]
action.add(items);
arrayMap.put(getIdentifier(items), items); // id = QUJDYWFh
//....
//Directly finding the twin will fail
String[] toSearch = new String[]{"apple","pear", "banana"}; // *[1556]
System.out.println(action.contains(toSearch)); // false
//But if we get the identifier based on the values
String arrId = getIdentifier(toSearch); // id = QUJDYWFh
System.out.println(action.contains(arrayMap.get(arrId))); //true
//arrayMap.get(arrId)-> *[1234]
//.....
Name.
Choose a representative name and use it as Id
Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"};
action.add(items);
arrayMap.put("fruits", items);
//...
System.out.println(action.contains(arrayMap.get("fruits"))); // true
The 'contains' method compares equivalent hashCode values.
So if you make it like below*, it will pass.
public class main {
public static void main(String[] args) {
ArrayList<String[]> action = new ArrayList<String[]>();
String[] items = new String[]{"appple","ball"};
action.add(items);
System.out.println("TO STRING");
System.out.println("--"+action.get(0));
System.out.println("--"+new String[]{"apple","ball"});
System.out.println("HASHCODES");
String[] sameValues = new String[]{"apple","ball"};
System.out.println("--"+action.get(0).hashCode());
System.out.println("--"+items.hashCode());
System.out.println("--"+sameValues.hashCode());
System.out.println("CONTAINS");
System.out.println("--"+action.contains(items)); // *this
System.out.println("--"+action.contains(sameValues));
System.out.println("--"+action.contains(new String[]{"apple","ball"}));
}
}
result is:
TO STRING
--[Ljava.lang.String;#7b1d7fff
--[Ljava.lang.String;#299a06ac
HASHCODES
--1243554231
--1243554231
--2548778887
CONTAINS
--true
--false
--false
Regarding the code shown when printing the array, these don't override toString(), so you get:
getClass().getName() + '#' + Integer.toHexString(hashCode())
For example:
[Ljava.lang.String;#7b1d7fff
[ stands for single dimension array
Ljava.lang.String stands for the type
#
7b1d7fff Hex representation of the hashcode
However, if you want to compare the values, there is the following method.
public class main {
public static void main(String[] args) {
String[] items = new String[]{"apple","ball"};
ArrayList<String> action = new ArrayList<>(Arrays.asList(items));
if (action.contains("apple")) {
System.out.println("Yes");
}
}
}
You can iterate over this list and for each element, i.e. array, call Arrays.equals method to check equality of arrays until first match, or till the end of the list if none match. In this case it can return true for each element:
List<String[]> list = List.of(
new String[]{"appple", "ball"},
new String[]{"appple", "ball"});
String[] act = new String[]{"appple", "ball"};
System.out.println(list.stream()
.anyMatch(arr -> Arrays.equals(arr, act))); // true
This method internally calls String#equals method for each element of the array, i.e. String, so this code also returns true:
List<String[]> list = List.of(
new String[]{new String("appple"), new String("ball")},
new String[]{new String("appple"), new String("ball")});
String[] act = new String[]{new String("appple"), new String("ball")};
System.out.println(list.stream()
.anyMatch(arr -> Arrays.equals(arr, act))); // true
According to JavaDocs, "contains" method is using "equals" and "hashCode" methods in order to check whether an object is contained.
A leading question:
Do you know what's the implementation of "equals" for arrays?
Check it and you will probably understand your code's execution result (hint: ==).
As "Hovercraft Full Of Eels" said, a better design will be using a list of some Collection which you DO understand / control it's "equals" and "hashCode" methods.
Related
Cannot create nested ArrayList from Array in Java
I am trying to create a nested list from an array.
But I have a problem while converting Object to String:
Object[] array = new Object[] {
new String[] {"add, hack"},
new String[] {"add, hackerrank"},
new String[] {"find, hac"},
new String[] {"find, hak"}
};
List<List<String>> list = Arrays.asList(Arrays.asList((array.toString())));
So, how can I convert it properly?
Here is the method that reserves the List<List<String>>:
public static List<Integer> contacts(List<List<String>> queries) {
for (List<String> query : queries) {
String operation = query.get(0); // --> gives "add, hack" (I expect "add")
String word = query.get(1);
}
}
Every array inside the source array in your code like new String[] {"add, hack"} is treated as Object - that's all the compiler knows about it because array has been declared as Object[] (i.e. array of objects, not array of arrays objects, or array of arrays of strings).
Arrays.asList(array.toString()) - creates a list with a single element of type String. And when you invoke toString() on an array of any type, you will obtain a string containing the array's type and hash-based sequence of symbols after the at-sign #. In order to get a string representation of the array contents, you need to use static method toString() of the Arrays class.
This way you can approach the problem of casting an array of Object type
public static void main(String[] args) {
Object[][] array = new Object[][]{
new String[] {"add, hack"},
new String[] {"add, hackerrank"},
new String[] {"find, hac"},
{"find, hak"} // you can omit new String[] when assigning array while at the same time with initialization
};
List<List<String>> list = arraysToList(array, String.class);
System.out.println(list);
}
Generic method for casting, that expects a Class object as a parameter:
public static <T> List<List<T>> arraysToList(Object[][] array, Class<T> clazz) {
return Stream.of(array)
.map(arr -> Stream.of(arr).map(clazz::cast).toList())
.collect(Collectors.toList());
}
Output
[[add, hack], [add, hackerrank], [find, hac], [find, hak]]
Your Question is unclear as to your goal. Perhaps you want to generate text in a specific format. If so, add a method to the record class Query that returns a String object in your desired format.
If you need to split a single string containing non-alphabetic symbols into separate words, you can make use of the split() method:
str.split("[^\\p{Alpha}]+"); // returns an array of strings comprised of alphabetic symbols only
Use objects, not lists of arrays
The other Answers seem to be correct about your various problems. I will look at the bigger picture… Your design approach has ignored the the best feature of Java: object-oriented programming.
Your query pieces should be packaged as a class, a record.
record Query ( String verb , String noun ) {}
Apparently you are starting with a comma-separated string as inputs. So add a static factory method to parse each input.
record Query ( String verb , String noun ) {
// Factory method to instantiate `Query` object by parsing input string containing a pair of comma-separated values.
public static Query parse( final String input ) {
String[] parts = input.split( ", " ) ;
return new Query ( parts[0] , parts[1] ) ;
}
}
Skip the arrays, and use List or Set for their convenience.
List< Query > queries =
List.of(
Query.parse( "add, hack" ) , // Instantiates a `Query` object.
Query.parse( "add, hackerrank" ) ,
Query.parse( "find, hac" ) ,
Query.parse( "find, hak" )
)
;
Generating text
Report contents.
System.out.println( "queries = " + queries );
queries = [Query[verb=add, noun=hack], Query[verb=add, noun=hackerrank], Query[verb=find, noun=hac], Query[verb=find, noun=hak]]
Your Question is not clear as to its end goal. If your goal is to generate text in a particular format, add a method to your class. Here we add a method called report.
String report ( ) { return String.format( "{ %s, %s }" , this.verb , this.noun ); }
To use that report method, loop your objects, generating text for each.
queries.forEach( query -> System.out.println( query.report() ) );
{ add, hack }
{ add, hackerrank }
{ find, hac }
{ find, hak }
Caveat: In real work, we would do more to verify and validate. For example we would validate our input data to make sure the input string is non-null, non-blank, and composed of two parts. I omitted such code to keep the demo short and on-point.
One more solution assuming you want to start from Object[] array - first transforms to list of String[] using casting and then maps every String[] to List:
List<String[]> arrList = new ArrayList<>();
for (Object o : array)
arrList.add((String[]) o);
List<List<String>> strList = arrList.stream()
.map(Arrays::asList)
.collect(Collectors.toList());
In order to be an "array of arrays" it would need to be a 2-dimensional array:
String[][] arrays = new String[][] {new String[] {"add, hack"}, ...}
Then you could convert each array inside the array into an item in the list
List<List<String>> list = new ArrayList<>();
for (String[] array : arrays) {
list.add(Arrays.asList(array));
}
You can stream the array and then collect to a List:
Object[] array = new Object[] {
new String[] {"add, hack"},
new String[] {"add, hackerrank"},
new String[] {"find, hac"},
new String[] {"find, hak"}};
List<List<String>> list = Arrays.stream(array)
.map(String[].class::cast)
.map(arr -> arr[0].split(", "))
.map(Arrays::asList)
.collect(Collectors.toList());
System.out.println(list);
Output:
[[add, hack], [add, hackerrank], [find, hac], [find, hak]]
With JDK 16+ you can do:
List<List<String>> list = Arrays.stream(array)
.map(String[].class::cast)
.map(arr -> arr[0].split(", "))
.map(Arrays::asList)
.toList();
I have declared a map as below:
Map<String, String[]> test = new HashMap<String, String[]>();
I have a variable empnames which is an array and deptname is a String and i have declared the deptname and empnames as below:
String deptname = ['Department']
String empnames = [['Test1']['Test2']]
if (deptname != null)
{
if (test.containsKey(deptname))
{
///
}
else
{
test.put(deptname, new String[]{empnames});
}
}
If the test map already contains deptname key then what condition i should write in if condition to append new values to department?
Since you tagged for [grails], I assume a Groovy answer is appropriate too. You can use a Map with .withDefault{ ... } to provide the content in case the key is missing. E.g.
def data = [["x", ["a", "b"]], ["x", ["c", "d"]]]
def test = [:].withDefault{[]} // XXX
data.each{ k, vs ->
test[k].addAll(vs) // if there is no key `k`, create an empty array, so `.addAll` just works
}
println(test.inspect())
// => ['x':['a', 'b', 'c', 'd']]
You can use the new methods in Java 8 like putIfAbsent to add new entry if key is not present and computeIfPresent to append values to an existing key of a map.
An example would be:
public static void main(String[] args) {
Map<String, String[]> test = new HashMap<>();
String deptname = "Department";
String[] empnames = {"Test1", "Test2"};
if (deptname != null){
test.putIfAbsent(deptname, empnames);
test.computeIfPresent(deptname, (dept, value) -> {
List<String> list = new ArrayList<>(Arrays.asList(value));
list.add("Test3");
value = list.toArray(value);
return value;
});
}
for(String s : test.get("Department")){
System.out.println(s);
}
}
Here the putIfAbsent tests if the key is present, if not adds a new key-value entry. The computeIfAbsent on the other hand tests if the key is present, if yes it computes the new value for the existing key-value entry.
The output of the above code is:
Test1
Test2
Test3
This is because initially the key Department was not present in the map test, so it was added to it along with the value empnames as an array.
In the second operation the method computeIfPresent checked that the key Department was already in the map so it appended the new String Test3 to existing value array of [Test1, Test2].
The same can be done for an List instead of an array:
public static void main(String[] args) {
Map<String, List<String>> test = new HashMap<>();
String deptname = "Department";
List<String> empnames = new ArrayList(Arrays.asList("Test1", "Test2"));
if (deptname != null){
test.putIfAbsent(deptname, empnames);
test.computeIfPresent(deptname, (dept, value) -> {
value.add("Test3");
return value;
});
}
for(String s : test.get("Department")){
System.out.println(s);
}
}
ArrayList<String> departmentList;
if(test.containsKey(key)){
// if the key has already been used, then and add a new value to it
list = test.get(key);
list.add(value);
test.put(key, list);
} else {
// if the key hasn't been used yet, then create a new ArrayList<String> object, add the value
list = new ArrayList<String>();
list.add(value);
test.put(key, list);
}
As others have suggested, this would be easier if you had an ArrayList instead of String[].
But since you have a String[], you will have to make a new array of old_array's_size + list_to_add and copy over the values from the old array into the new one plus the new value you want to append.
So inside of your if statement:
String [] oldList = test.get(deptName);
String[] newList = new String[oldList.length + empnames.length]; //Make a new array with enough space for the previous values at deptname but also the new ones you want to add
//Put all of the values from the existing value at deptname into a new array
for (int i = 0; i < oldList.length; i++)
newList[i] = oldList[i];
//Put all of the values from the list of values you want to add into the new array
for (int i = 0; i < empnames.length; i++)
newList[oldList.length + i] = empnames[i];
test.put(deptname, newList); //Put the completed list back into the map
Again, if you used some kind of List this would be easier. One good reason besides being able to append is that you can easily sort it alphabetically using Collections.sort.
I am trying to iterate through many arrays, two at a time. They contain upwards of ten-thousand entries each, including the source. In which I am trying to assign each word to either a noun, verb, adjective, or adverb.
I can't seem to figure a way to compare two arrays without writing an if else statement thousands of times.
I searched on Google and SO for similar issues. I couldn't find anything to move me forward.
package wcs;
import dictionaryReader.dicReader;
import sourceReader.sourceReader;
public class Assigner {
private static String source[], snArray[], svArray[], sadvArray[], sadjArray[];
private static String nArray[], vArray[], advArray[], adjArray[];
private static boolean finished = false;
public static void sourceAssign() {
sourceReader srcRead = new sourceReader();
//dicReader dic = new dicReader();
String[] nArray = dicReader.getnArray(), vArray = dicReader.getvArray(), advArray = dicReader.getAdvArray(),
adjArray = dicReader.getAdjArray();
String source[] = srcRead.getSource();
// Noun Store
for (int i = 0; i < source.length; i++) {
if (source[i] == dicReader.getnArray()[i]) {
source[i] = dicReader.getnArray()[i];
}else{
}
}
// Verb Store
// Adverb Store
// Adjective Store
}
}
Basically this is a simpler way to get a list of items that are in both Lists
// construct a list of item for first list
List<String> firstList = new ArrayList<>(Arrays.asList(new String[0])); // add items
//this function will only keep items in `firstList` if the value is in both lists
firstList.retainAll(Arrays.asList(new String[0]));
// iterate to do your work
for(String val:firstList) {
}
have this class
public class ObjetoOS {
private ArrayList<String> atribute = new ArrayList<String>();
public ObjetoOS (String a){
atribute.add(a);
}
public ObjetoOS (ArrayList<String> a){
atribute = a;
}
which i use like this
public class TablaSimbolica {
private static ArrayList<ObjetoOS> tableOS = null;
public static void addAtributos(ArrayList<String> newOnes){
if (tableOS == null){
tableOS = new ArrayList<ObjetoOS>();
for (String s : newOnes){
ObjetoOS newObj = new ObjetoOS(s);
tableOS.add(newObj);
}
}
else{
ArrayList<ObjetoOS> aux = new ArrayList<ObjetoOS>();
for (ObjetoOS os : tableOS){
ArrayList<String> oldOnes = new ArrayList<String>();
oldOnes = os.getAtributo();
for (String s : newOnes){
oldOnes.add(s);
ObjetoOS newObj = new ObjetoOS(oldOnes);
aux.add(newObj);
newObj = null;
oldOnes.remove(s);
}
}
tableOS = aux;
}
}
so basically: addAtributos checks if the array its empty. if it is it just adds the strings, if its not, i have to combine it with the new ones, like a cartisan product thing.
when adding new strings, although im creating a new array, and a new objectOS which y turn to null after adding it, the elements overwrite with the last one.
for example, if i had strings "true" "false", and i have to add "female" "male", the output is:
[TRUE, Female]
[TRUE, Male]
[TRUE, Male]
[TRUE]
[TRUE]
[FALSE, Female]
[TRUE]
[TRUE]
[FALSE, Male]
[FALSE, Male]
i cant figure out where im missing the point here. it gives me an error if i erase the static both from the ArrayList tablaOS or from the addAtributos method.
EDIT: solved! i changed the object class making a new empty constructor and a method adding a string array with a for.
the loop it ended up being
for (String s : newOnes){
oldOnes.add(s);
ObjetoOS nuevo = new ObjetoOS();
nuevo.addAtribute(oldOnes);
aux.add(nuevo);
oldOnes.remove(s);
Some of your problems lies here:
ArrayList<String> oldOnes= new ArrayList<String>(); // This line is pointless
oldOnes= os.getAtributo(); // oldOnes will be overwritten here
for (String s : newOnes)
{
oldOnes.add(s);
ObjetoOS newObj = new ObjetoOS(oldOnes);
aux.add(newObj );
newObj = null;
oldOnes.remove(s);
}
When you here pass oldOnes to the ObjetoOS constructor, the newObj will have a reference to the same list as oldOnes, when you then later remove the element from oldOnes you also remove it from newObj's list(since they are the same).
The same does not happen if you use the String constructor because primitive datatypes, also including Strings, are copied (passed by value) when passed to a method.
There's a good explanation on how objects are passed in java here: Is Java "pass-by-reference" or "pass-by-value"?
Edit:
Also your tableOS will point to a new ArrayList<> every time you call your method, if I understand your solution correctly this might be more what you want:
...
for (ObjetoOS os : tableOS)
{
for (String s : newOnes)
{
ArrayList<String> oldOnesPlusNewOne = new ArrayList<>();
oldOnesPlusNewOne.addAll(os.getAtributo());
oldOnesPlusNewOne.add(s);
ObjetoOS newObj = new ObjetoOS(oldOnesPlusNewOne);
tableOS.add(newObj);
}
}
Might I suggest simplifying the code some? If your trying to add attributes to an array list, maybe create an attributes class instead. You can create a class for the atributos, give it some members etc... and easily change to and make the atributos a list to hold aritbutos. I'd suggest the class be name Atributo. Your trying to do to much in one class. Single responsibility is key. One class that defines the atributo and one to store a list of them. This should fix your problem and uncomplicate your code. Now you can only store 10 members to the array list without specifying the amount of elements you want it to hold. If you don't it will only hold the default of 10 and the last element will be over written.
import java.util.ArrayList;
public class Atributos
{
// attributes list
ArrayList<String> atributos = new ArrayList<String>();
// add string to attributes list
public void addAtributos(String atributo)
{
atributos.add(atributo);
}
// add list of strings to attribute list
public void addAtributos(ArrayList<String> atributo)
{
for(String attr : atributo)
{
atributos.add(attr);
}
}
}
I have a series of String[] arrays which are list of words. Something like:
String[] ListOne = new String[100];
String[] ListTwo = new String[100];
/*And so on with other lists */
ListOne[0] = "word00";
ListOne[1] = "word01";
/*And so on till*/
ListLast[99] = "word 99 from last list";
Now I want a function for each list that, given a number returns the corresponding element (word):
public String GetFromListOne(int key) { return ListOne[key];}
Is there a way to avoid manually writing each of this getter functions?
In PHP, for example, I would just use the magic method __call,
or pass as an argument with the list name and reference it dynamically.
Is there a way to do something similar in Java?
Or an alternative strategy to achieve the same result?
You should look into inheritance.
What you basically must do is define an interface (or extend a List class)
public interface ListTest{
//**Gets keys from lists*//
GetFromListOne(int key);
}
then
public class Listone implements ListTest{
/** methods **//
GetFromListOne(int key);
/** methods **//
}
Have fun extending
http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html
You could use a 2 dimensional array, or a list of arrays and have your function take 2 parameters. One for the array that you want and the other for the element in the array.
2 dimensional array:
String[][] ListN = new String[100,100];
String getFromList(int n, int key) {
return ListN[n][key];
}
Or list of arrays:
List<String[]> listOfArrays = new ArrayList<String[]>();
listOfArrays.add(new String[100]);
listOfArrays.add(new String[100]);
String getFromList(int n, int key) {
return listOfArrays.get(n)[key];
}
Could you have a function that takes as input the key and the list number:
public String GetFromListOne(int list, int key) {
switch(list):
case 1:
return ListOne[key];
break;
case 2:
return ListTwo[key];
break;
...
}
or even better make an array of arrays:
String[][] ListOfLists = new String[10];
ListOfLists[0] = new String[100];
...
public String GetFromList(int list, int key) {
return ListOfLists[list][key];
}
Otherwise I don't know of a function to override like __call
String[] ListFour=new String[100];
String[] ListTwentyThree=new String[100];
String[] ListNine=new String[100];
String[] ListOne=new String[100];
Hashtable<Integer,String[]> yourlist=new Hashtable<Integer,String[]>();
yourlist.put(4, ListFour);
yourlist.put(23, ListTwentyThree);
yourlist.put(9, ListNine);
yourlist.put(1, ListOne);
System.out.println(yourlist.get(4)[5]);//fifth string in ListFour
System.out.println(yourlist.get(23)[51]);//fifty first string in List23
System.out.println(yourlist.get(9)[1]);//first stringin ListNine
another version:
Hashtable<Object,String[]> yourlist=new Hashtable<Object,String[]>();
yourlist.put("two multiplied by two", ListFour);
yourlist.put(23, ListTwentyThree);
yourlist.put(0.03, ListNine);
yourlist.put(true, ListOne);
System.out.println(yourlist.get("two multiplied by two")[5]);//fifth string in ListFour
System.out.println(yourlist.get(23)[51]);//fifty first string in List23
System.out.println(yourlist.get(true)[1]);//first stringin ListNine
Based in the __call PHP method, you can achieve this implementing a method that receives the list and the index, and using generics you can get something like this.
public class Utility {
public <T> T getElementFromArray(T[] array, int index) {
if (index >= array.length || index < 0) return null;
return array[index];
}
}
The pitfall of this method is that can't be used for primitive array holders, like int[]. The solution for these cases would be using the wrapper classes for primitive types.
public static void main(String[] args) {
Utility u = new Utility();
String[] ss = new String[2];
ss[0] = "Hello";
ss[1] = "world!";
System.out.println(u.getElementFromArray(ss, 0));
System.out.println(u.getElementFromArray(ss, 1));
int[] ii = new int[2];
ii[0] = 5;
System.out.println(u.getElementFromArray(ii, 0)); //compile error
//Solution: use wrapper classes
Integer[] ii2 = new Integer[2];
ii2[0] = 5;
System.out.println(u.getElementFromArray(ii2, 0));
}
Try this code
List<String[]> lists = new ArrayList<String[]>();
public String getFromLists(int key) {
List<String> res = new ArrayList<String>();
for (String[] s: lists){
res.add(s[key]);
}
return res.get(key);
}
or better
public String getFromLists(int key) {
return lists.get(key)[key];
}