Java: deepcopy list entry without instancing a new list - java

I've got a little problem while doing my programming task. I want to read some lines from a file (no problem so far) and tokenize it. Every line has about 4 tokens and each of them should find a place in a list. In the end, every line should be in a list too.
A little example to clarify this:
File Content:
foo boo barbii buu baa
output:
[[foo, boo, bar], [bii, buu, baa]]
And heres the code I'm dealing with
String fileContent = fileloader(file.toString());
List<String> linesList = new ArrayList<String>();
String[] lines = fileContent.split("\n");
for(String line:lines){
String[] splittedLine = line.split("\t");
for(String words:splittedLine){
linesList.add(words);
}
lexiconContent.add(linesList);
linesList.removeAll(linesList);
}
I guess there's a problem with the references, because the first iteration works well! But in the second iteration, it copies the actual second content also to the first (0) list position and so on.
Finally I got something like [[], [], [], []]

The problem is that, you have created only one list, and adding a reference to that list to your outer list, by modifying it on each iteration. So, the final modification done to that list will be reflected for all the references.
You can solve this problem by creating a new linesList each time in the loop: -
List<String> linesList = null; // Don't initialize here
String[] lines = fileContent.split("\n");
for(String line:lines){
String[] splittedLine = line.split("\t");
linesList = new ArrayList<String>(); // Initialize a new list everytime.
for(String words:splittedLine){
linesList.add(words);
}
lexiconContent.add(linesList);
}
And yes, you can also simplify your for loop to: -
for(String line:lines){
String[] splittedLine = line.split("\t");
lexiconContent.add(new ArrayList<String>(Arrays.asList(splittedLine)));
}
This way, you don't have to iterate over your array, and add individual elements to your List. In fact, you don't need an intermediate list at all.

In your code..Instead of creating new ArrayList for each iteration in loop: for(String line:lines) You are just adding the words (in nested loop) in the old object of ArrayList that you had used right from the first iteration of outer loop and storing that same reference value at all subsequent index of lexiconContent ArrayList.Also at the end of each iteration of outer loop you are clearing the linesList .So Finally you are remained with N number of entries in lexiconContent...Where the Element at each index of lexiconContent is nothing but the reference value of the single object of ArrayList(lineList) which is Empty!!!
You should use following code instead:
String fileContent = fileloader(file.toString());
List<String> linesList = null;
String[] lines = fileContent.split("\n");
for(String line:lines){
List<String> linesList = new ArrayList<String>();
String[] splittedLine = line.split("\t");
for(String words:splittedLine){
linesList.add(words);
}
lexiconContent.add(linesList);
}

Related

Converting List<List<String>> to array

I have elements that is declared in a list variable such as:
List<List<String>> textList = new ArrayList<>();
The elements are added such as:
textList.add(Arrays.asList(p)); //adding elements
The only way I could output the elements inside the variable is by using:
for(List<String> s: textList){
System.out.println(s); }
which output elements like this:
[He is a boy.]
[He likes apple.]
[She is a girl.]
Now, I would like to store them in an array so that the elements will look like this when outputted.
[He is a boy., He likes apple., She is a girl.]
I've tried
String[] textArr = new String[textList.size()];
textArr = textList.toArray(textArr);
for(String s : textArr){
System.out.println(s);}
but I got an error about:
Exception in thread "main" java.lang.ArrayStoreException
at java.lang.System.arraycopy(Native Method)
at java.util.Arrays.copyOf(Arrays.java:3213)
at java.util.ArrayList.toArray(ArrayList.java:407)
So, how do I convert the elements inside a list into array using the proper way. Thanks!
Your problem is that you are not storing Strings in your list textList.
textList.add(Arrays.asList(p));
As the type says, you have a List of List of String here.
So you can't take the elements of that list and assume they are Strings. Because they aren't! The error message tells you that: toArray() wants strings it can put into that array of strings, but you give it a List of List of String!
But thing is: what you are describing here doesn't make sense in the first place. Printing strings shouldn't care if strings are in an array or a List.
What I mean is: when you manually iterate a List or an array to print its content, then it absolutely doesn't matter if you iterate a List or an array. The code is even the same:
for (String someString : someCollection) {
System.out.println(someString);
}
someCollection can be both: array or List!
In other words: the idea to turn data that is nicely stored within Lists into arrays for printing simply doesn't make any sense. To the contrary: you are probably calling toString() on your List object, and the result of that ... isn't 100% what you want. But I guarantee you: calling toString() on some array will result in something you totally will not want.
Long story short: forget about converting to Arrays; simply iterate your List of List of Strings and use a StringBuilder to collect the content of that collection the way you want to see it (you simply append those [ ] chars to that builder in those places you want them to see).
(if you insist on that conversion to array, the key point there to understand is that only a List of String can be turned into an array of string. So a List of List ... doesnt work that easy).
Using streams and flatMap, you can do this:
List<List<String>> list = ...;
String[] strings = list.stream().flatMap(l -> l.stream()).collect(Collectors.toList()).toArray(new String[0]);
This is equivalent to using a loop (You can use two nested for loops as suggested in the comments instead by replacing the addAll, but why?):
List<List<String>> list = ...;
List<String> stringList = new ArrayList<>();
for (List<String> l : list)
stringList.addAll(l);
String[] strings = list.toArray(new String[stringList.size()]);
You can use Iterator in order to go over every element of the list, instance of the for each statement (I personally like the iterators more). The code you could use would be something like
//Your list
List<List<String>> textList = new ArrayList<>();
//The iterators
Iterator<List<String>> itList = textList.iterator();
Iterator<String> itString;
//The string to store the phrases
String s[] = new String[textList.size()];
int i =0;
//First loop, this seeks on every list of lists
while(itList.hasNext()){
//Getting the iterator of strings
itString = itList.next().iterator();
s[i] = "";
//2nd loop, it seeks on every List of string
while(itString.hasNext()){
s[i] = s[i].concat(itString.next());
}
s[i] = s[i].concat(".");
i++;
}

comparing list1 and list2, remove duplicate from list2 (not working with removeAll() )

I am trying to compare two lists where I want to check for duplicates. If list1 and list2 contains the same duplicate then the duplicate from list2 should be removed.
I've been able to solve the problem if I compare two .txt file or where list1 is a .txt file while list2 is hardcoded. Thus, if:
list1 contains stuff from a .txt file (which is like a template) and list2 is fetched from another place my code won't work.
Below you can see my code:
public static String removeLinesFromTemplate(String text) throws IOException{
final List<String> list = new ArrayList<String>();
final List<String> list2 = new ArrayList<String>();
// New BufferedReader.
final BufferedReader reader = new BufferedReader(new FileReader("testing"));
//Add all lines from the file testing to the arraylist.
String row;
while ((row = reader.readLine()) != null) {
list.add(row.toLowerCase());
}
// Close it.
reader.close();
System.out.println(list);
list2.add(text.toLowerCase());
//If two lines matches between list2 and list, then that line will be removed from list2.
list2.removeAll(list);
System.out.println(list2);
// Convert the list into string
String listString = "";
for (String s : list2){
listString += s ;
}
return listString;
}
It seems like my list2.removeAll(list) won't work and remove the duplicates. Any ideas why, and how do I solve
I tried #SeniorJD's option3
String[] parts = text.split("\\s+");
for(String item : parts){
list2.add(item.toLowerCase());
}
The problem still stays, example:
list1: 1 monkey, -------, (input of list1)
list2: 1 monkey, -------, asdf, (input of list2)
Issue here right now is that 1 monkey is not being removed, while "------" gets removed.
So the output of list2 is: 1 monkey, asdf,
Seems U don't understand how String and Collections work.
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
list1.add("a");
list1.add("b");
// #way1 - would not work
list2.add("a b c");
list2.removeAll(list1);
// #way2 - would work
list2.add("a");
list2.add("b");
list2.add("c");
list2.removeAll(list1);
// #way3 - would work as well
String text = "a b c";
String[] parts = text.split("\\s+");
for (String part: parts) {
list2.add(part);
}
list2.removeAll(list1);
Why?
String is a set of chars, List is a set of Objects (in our example - String Objects). When U try #way1, the list2 looks for the equal object it already has. "a b c" not equals to "a", or "b". So it is not working as U expected. Try #way2 and debug it, and learn the Java Core first.
Your list2 contains only one element(the whole text). The elements of list are lines from the parsed file. So in order for the removeAll to work you need to transform the the text variable into a list of lines.

Add multiple numbered objects to ArrayList

Suppose I have a lot of String Variables(100 for example):
String str1 = "abc";
String str2 = "123";
String str3 = "aaa";
....
String str100 = "zzz";
I want to add these String variables to ArrayList, what I am doing now is
ArrayList<String> list = new ArrayList<String>();
list.add(str1);
list.add(str2);
list.add(str3);
...
list.add(str100);
I am curious, is there a way to use a loop? For example.
for(int i = 1; i <= 100; i++){
list.add(str+i)//something like this?
}
Use an array:
String[] strs = { "abc","123","zzz" };
for(int i = 0; i < strs.length; i++){
list.add(strs[i]); //something like this?
}
This idea is so popular that there's built-in methods to do it. For example:
list.addAll( Arrays.asList(strs) );
will add your array elements to an existing list. Also the Collections class (note the s at the end) has static methods that work for all Collection classes and do not require calling Arrays.asList(). For example:
Collections.addAll( list, strs );
Collections.addAll( list, "Larry", "Moe", "Curly" );
If you just want a list with only the array elements, you can do it on one line:
List<String> list = Arrays.asList( strs );
Edit: Many other classes in the Java API support this addAll() method. It's part of the Collection interface. Other classes like Stack, List, Deque, Queue, Set, and so forth implement Collection and therefore the addAll() method. (Yes some of those are interfaces but they still implement Collection.)
If you are using Java 9 then easily you can add the multiple String Objects into Array List Like
List<String> strings = List.of("abc","123","zzz");
If you want to stick to good practice, declare your Strings in an array:
String[] strs = new String[]{ "abc", "123", "aaa", ... };
for (String s : strs) // Goes through all entries of strs in ascending index order (foreach over array)
list.add(s);
If strX would be class fields then you could try using reflection - link to example of accessing fields and methods.
If it is local variable then you can't get access to its name so you will not be able to do it (unless str would be array, so you could access its values via str[i] but then you probably wouldn't need ArrayList).
Update:
After you updated question and showed that you have 100 variables
String str1 = "abc";
String str2 = "123";
String str3 = "aaa";
//...
String str100 = "zzz";
I must say that you need array. Arrays ware introduced to programming languages precisely to avoid situation you are in now. So instead of declaring 100 separate variables you should use
String[] str = {"abc", "123", "aaa", ... , "zzz"};
and then access values via str[index] where index is value between 0 and size of your array -1, which in you case would be range 0 - 99.
If you would still would need to put all array elements to list you could use
List<String> elements = new ArrayList<>(Arrays.asList(str));
which would first
Arrays.asList(str)
create list backed up by str array (this means that if you do any changes to array it will be reflected in list, and vice-versa, changes done to list from this method would affect str array).
To avoid making list dependant on state of array we can create separate list which would copy elements from earlier list to its own array. We can simply do it by using constructor
new ArrayList<>(Arrays.asList(str));
or we can separate these steps more with
List<String> elements = new ArrayList<>();//empty list
elements.addAll(Arrays.asList(str));//copy all elements from one list to another
Yes. The way to use a loop is not to declare 100 string variables. Use one array instead.
String[] str = new String[101];
str[1] = "abc";
str[2] = "123";
str[3] = "aaa";
....
str[100] = "zzz";
(I made the indexes go from 1 to 100 to show how it corresponds to your original code, but it's more normal to go from 0 to 99 instead, and to initialize it with an array initializer as in #markspace's answer.)
The following creates the ArrayList on the specific String values you have:
ArrayList<String> list1 = new ArrayList<String>() {{addAll(Arrays.asList(new String[]{"99", "bb", "zz"}));}};
Or, if it's just some distinct values you want, use this for say - 10 of them:
ArrayList<String> list2 = new ArrayList<String>() {{for (int i=0; i<10; i++) add(""+System.currentTimeMillis());}};

Java- Add each word to an arraylist?

this may be pretty simple, but for some reason I am blanking right now.
Suppose I had a string "Hello I Like Sports"
How would I add each word to an arraylist (so each word is in an index in the arraylist)?
Thanks in advance!
ArrayList<String> wordArrayList = new ArrayList<String>();
for(String word : "Hello I like Sports".split(" ")) {
wordArrayList.add(word);
}
The first thing to do is to split that sentence up into pieces. The way to do that is to use String.split That will return an Array of Strings.
Since you want it in an ArrayList, the next thing you have to do is loop through every String in the array and add it to an ArrayList
String[] words = sentence.split(" ");
list.addAll(Arrays.asList(words));
Try this:
public static void main(String[] args) {
String stri="Hello I Like Sports";
String strar[]=stri.split(" ");
ArrayList<String> arr = new ArrayList<String>(Arrays.asList(strar));
for(int x=0;x<arr.size();x++){
System.out.println("Data :"+arr.get(x));
}
}
Output :
Data :Hello
Data :I
Data :Like
Data :Sports
you can use the split method of the String and split on spaces to get each word in a String array. You can then use that array to create an arrayList
String sentence ="Hello I Like Sports";
String [] words = sentence.split(" ");
ArrayList<String> wordList = new ArrayList<String>(Arrays.asList(words));
String.split()
Arrays.asList()
A little search would have done the work.
Still I am giving a solution to this. You can use Split.
You can later add those array elements to arraylist if you require.
String s="Hello I like Sports";
String[] words = s.split(" "); //getting into array
//adding array elements to arraylist using enhanced for loop
List<String> wordList=new ArrayList();
for(String str:words)
{
wordList.add(str);
}
First, you have to split the string, and :
if you want a List, use Arrays.asList
if you want an ArrayList, create one from this List.
Sample code :
final String str = "Hello I Like Sports";
// Create a List
final List<String> list = Arrays.asList(str.split(" "));
// Create an ArrayList
final ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(str.split(" ")));
Using Arrays.asList and the ArrayList constructor avoids you to iterate on each element of the list manually.
try this code was perfect work for get all word from .txt file
reader = new BufferedReader(
new InputStreamReader(getAssets().open("inputNews.txt")));
// do reading, usually loop until end of file reading
String mLine;
while ((mLine = reader.readLine()) != null) {
for(String word :mLine.split(" ")) {
lst.add(word);
}
}

What is the best and optimal solution to iterate thought list of array of strings and get its value out?

I have list of array of strings, List <String []>, what is the best optimal approach to get contents of this list of array of strings?
public List<String []> readFromString (String data){
StringReader stringReader = new StringReader(data);
CVSReader reader = new CVSReader(stringReader);
return reader.readAll()
}
In above example, I want to see the actual contain of reader.readAll(), any suggestions as to what is the optimal way to get that information out?
I don't think there's any avoiding looping through the entire structure. Even if you call .toString(), which may well give what you want, you're still going to incur the cost of looping over the entire data structure:
String results = readFromString(data);
StringBuilder output = new StringBuilder();
for(String[] sArray : results) {
for(String s : sArray) {
output.append(s);
}
}
System.out.println(output);
(Note: insert formatting characters as required - you might want to put a comma after each string, and a \n after each list completes, to make the output more readable.)
By wanting to see the content and "get information out", if you mean that you want to send it to standard out, or your log file, to see a full dump of the data, you can use the List toString (i.e. System.out.println(reader.readAll()); ). It prints all values. The following unit test confirms it:
public void testListOfArraysToStringPrintsAllValues(){
String[] array1 = ["array1.1", "array1.2"];
String[] array2 = ["array2.1", "array2.2"];
List<String[]> listOfArrays = new ArrayList<String[]>();
listOfArrays.add(array1);
listOfArrays.add(array2);
assertEquals("[[array1.1, array1.2], [array2.1, array2.2]]", listOfArrays.toString());
}
Are you looking for something like this?
for(String[] sArray : new CVSReader(new StringReader(data)).readAll())
{
for(String s : sArray)
{
System.out.prinntln(s);
}
System.out.prinntln("*********");
}
I can be wrong but my suggetions are:
To separte the lines:
String[] lines = data.split("\n");
To get a java.util.List
java.util.Arrays.asList(lines)
To separate each line:
String[] fields = line.split(",");
where line will be one of the String[] lines element.

Categories

Resources