I use while loop to read a text file and create new arraylists out of portions of the text file and then place those arraylists inside another arraylist. My problem is that I don't know how to add my temporary arraylist parse into the mainAList and then clear it for the next loop without affecting all the parse arraylists inside the arraylist<arraylist> mainAList. More info inside the comments below in the code.
This is a sample code, it is from larger file. It is shortened but has all the moving parts
ArrayList<ArrayList<String>> mainAList = new ArrayList<ArrayList<String>>();
ArrayList<String> parse = new ArrayList<>();
try (Scanner filereader = new Scanner(Paths.get("name_of_file.txt"))) {
while (filereader.hasNextLine()) {
parse.add(filereader.nextLine());
if (parse.get(parse.size()-1).length() == 0 || !filereader.hasNextLine()) {
// if the file reader detects empty line or has no more lines
// the arraylist called parse gets added to the mainAList
mainAList.add(parse);
}
parse.clear();
// here is my problem. How do I clear parse so for the next patch of lines
// so I don't add the same things + more into the next slot of mainAList
// every time the loop runs?
// I understand my issue is not how to correctly clear the parse but
// how to add the arraylists correctly into the mainAList so I can alter them individually
}
}
The file that is read is like this:
a
b
c
d
f
g
h
i
j
k
l
etc..
There are two problems with your current approach:
parse will use the same reference for all inner ArrayLists, so when you call parse.clear() it will empty all inner lists of your mainAList. This can be solved by creating a copy of the parse list when you add it (i.e. mainAList.add(new ArrayList<>(parse));)
You want to clear the list inside the if as well, after you've added the copy to your mainAList.
In addition, I assume you don't want the empty lines added to the individual inner Lists, so you could read the line first, and either add the entire list to mainAList and clear parse inside the if-statement, or add the line to the parse-list.
A slightly better alternative, is to just create a new list instead, so you won't need the clear and creating a copy of the list.
In total:
ArrayList<ArrayList<String>> mainAList = new ArrayList<ArrayList<String>>();
ArrayList<String> parse = new ArrayList<>();
try (Scanner filereader = new Scanner(System.in)) {
while (filereader.hasNextLine()) {
String line = filereader.nextLine();
if (line.length() == 0 || !filereader.hasNextLine()) {
// if the file reader detects empty line or has no more lines
// the arraylist called parse gets added to the mainAList
mainAList.add(parse);
// and then a new parse-list is created for the next group of inputs:
parse = new ArrayList<>();
} else{
parse.add(line);
}
}
}
Try it online.
Try this instead of clearing the list everytime.
ArrayList<ArrayList<String>> mainAList = new ArrayList<ArrayList<String>>();
try (Scanner filereader = new Scanner(Paths.get("name_of_file.txt"))) {
while (filereader.hasNextLine()) {
ArrayList<String> parse = new ArrayList<>();
parse.add(filereader.nextLine());
if (parse.get(parse.size()-1).length() == 0 || !filereader.hasNextLine()) {
mainAList.add(parse);
}
}
}
Your problem is that your mainAList will be empty in the end because objects are reference types. In order to fix that problem, you have to add a copy of parse to the mainAList and not the parse arraylist itself
replace this line
mainAList.add(parse);
with this
mainAList.add(new ArrayList<>(parse));
Related
I want to take the contents of a CSV file and remove the duplicates in it. This is a topic that's gotten a lot of coverage here and elsewhere, but none of the suggested methods work for me: the final result still contains the duplicate values.
These are the steps I'm taking to get the text from the CSV file:
String holder = "";
Scanner input = new Scanner(new File("C:"+File.separator+"followers.csv")).useDelimiter(",");
List<String> temp = new ArrayList<String>();
while (input.hasNext())
{
holder = input.next();
temp.add(holder);
}
input.close();
So far, so good.
After trying to turn the ArrayList into a LinkedHashSet and a whole lot else, to no avail, this is what I'm on currently:
List<String> finalList = new ArrayList<String>();
for (String s : temp)
{
if (!finalList.contains(s))
{
finalList.add(s);
}
}
finalList.forEach(System.out::println);
But finalList still contains the duplicate values.
I'm assuming the problem lies with how I'm getting the CSV values into the ArrayList in the first place, but I have no idea where I'm going wrong.
An elegant solution to remove duplicates (without keeping the order) is
Set<String> hs = new HashSet<>();
//assume the ArrayList temp contains your data with duplicates
hs.addAll(temp);
temp.clear();
temp.addAll(hs);
temp then contains your data without duplicates.
You are probably getting whitespaces and new lines mixed with your values, hence the duplicates. Try parsing with uniVocity-parsers CsvParser as it eliminates these for you, works faster, and gives you much better support for handling the CSV format in general.
Try this to eliminate your dupes:
CsvParserSettings settings = new CsvParserSettings();
settings.getFormat().setLineSeparator("\n");
// creates a CSV parser
CsvParser parser = new CsvParser(settings);
// parses all rows in one go.
List<String[]> allRows = parser.parseAll(new File("C:"+File.separator+"followers.csv")));
Set<String> result = new LinkedHashSet<>();
for(String[] row : allRows){
for(String element : row){
if(element != null){
//assuming the case of these these elements don't matter
//remove the ".toLowerCase()" part if it does.
result.add(element.toLowerCase());
}
}
}
System.out.println(result); //here's your deduplicated data.
Hope it helps.
Disclosure: I'm the author of this libary, it's open-source and free (Apache 2.0 License)
I am reading from a text file and saving the lines into an ArrayList. But I have had no success in how to go through and read all of the specific characters in the ArrayList, how many columns and rows there are.
This is the code I have written so far:
String line;
BufferedReader br = new BufferedReader(r);
ArrayList<String> myArrayList = new ArrayList<String>();
while ((line = br.readLine()) != null)
{
myArrayList.add(line);
.........
}
If I am reading your post right you are wanting to further break apart your lines (your reference to columns). Since you are storing String objects you will need to further break apart those entries into another List to truly parse through your words and characters appropriately.
Java used to have something called the StringTokenizer which could do what you want but that is now deprecated and replaced by the String.Split() method. By iterating through your ArrayList and splitting the String Object by specific delimiters (such as a space or a period), you should be able to further breakdown your existing ArrayList and create a new List with individual words, or even characters.
I do not know why you use "store.add(line)". You should use myArrayList instead of this.
After you have stored everything in the ArrayList you can use a for-each loop to traverse through the list:
for (String string : myArrayList) {
// do everything with the strings here
}
You aren't calling the List myArrayList, I think you want to change this
ArrayList<String> myArrayList = new ArrayList<String>();
to (using the diamond operator and the interface type) -
List<String> store = new ArrayList<>(); // <-- match the name.
You can count the "rows" by getting the size of the List -
int rows = store.size();
To count "columns" you would need to iterate the List and examine the lines. (or you could do that while you read the input) -
for (String line : store) {
// count columns in line
}
If you want to go through a ArrayList there are many ways that you can try
You can easily get number of elements in the ArrayList using size() method.
e.g.
//traditional way
for(int i = 0; i< arrayList.size(); i++){
System.out.println(arrayList.get(i));
}
//enhanced forloop
if your ArrayList is String type
for(String row : arrayList)
System.out.println(row);
With Java 8 you cane have more easier iterator that can use to go through the ArrayList
Edited
If you wanna read character by character
for(String row : arrayList){
char []letters = row/toCharArray();
for(char character : letters)
System.out.print(character + " ") ;
}
I'm trying to remove an item from an Text file using an arrayList. The ArrayList get's its values from the Text File, and then it displays it in a ListView.
I have a contextual menu that pops up, and gives me an option to remove the item from the list.
In the text file, all the items are on a new line.
How will I go about removing specific items from the file? The ArrayList will clear it's self, and pull the data into the ArrayList when ever the action has been performed, so that is sorted.
Code to remove item from array:
int id = info.position;
for(int i = array.size()-1; i >=0; i--){
array.remove(id);
}
File != ArrayList, ArrayList don't know anything about File and File don't know anything about ArrayList.
A way to do what you want is to rewrite again the data inside the file when you need it (when you delete an item from an ArrayList, call a method which updates the TextFile)
You should call it before ArrayList clear (or you will lose every value!)
An example:
List<String> values = new ArrayList<String>();
values.add("A");
values.add("B");
values.add("C");
values.add("D");
values.add("E");
values.add("D");
BufferedWriter fileWriter = null;
try
{
fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("fileName.txt")));
for (String value : values)
{
fileWriter.write(value + System.getProperty("line.separator"));
}
}
finally
{
if (fileWriter != null)
fileWriter.close();
}
I think it's a safe way to do this without depend much to the fact that the file is not changed by another source (in any way)
If each item in the ArrayList is equivalent to each line in the file, then just keep track of the index of the position of deleted item in the ArrayList. Then rewrite the entire file except that tracked index (which should be that same line).
Basically, once you delete the item from you ArrayList, then just write over the file as you loop through your updated ArrayList.
I have two array list with different size. How to Replace from this:
ArrayList<String> s = new ArrayList<String>();
ArrayList<String> f = new ArrayList<String>();
s.add("Nepal");
s.add("Korea");
s.add("Sri Lanka");
s.add("India");
s.add("Pakistan");
s.add("China");
s.add("Australia");
s.add("Bhutan");
f.add("London");
f.add("New York");
f.add("Mumbai");
f.add("sydeny");
for(int i=0;i<s.size();i++){
// Collections.copy(f, s);
f.addAll(s);
Log.d("TAG", "Sources---" + s.get(i));
Log.d("TAG", "Dest---" + f.get(i));
}
I have try both this. but not replace only append or copy from the existing array list.
My aim is totally replace original array to new arraylist.
You may do clear() first and then do addAll(s);
After clear() your arraylist will be empty.
EDIT:
As #Luggi commented, clear() will not be good option if list is big, instead simply point your f reference to new ArrayList with collection as parameter:
Example:
f = new ArrayList(s);
enter link description hereenter link description hereYou can do this in many ways
First clear then add all
f.clear();
f.addAll(S);
By first way all element copy from one list to another list if you want that both the list are same and manipulation in one list reflects in another list then you can point both on the same list like
f = s;
By intializing new list by adding all element into a new list.
f = new ArrayList(s);
ArrayList<String> s = new ArrayList<String>();
ArrayList<String> f = new ArrayList<String>();
s.add("Nepal");
s.add("Korea");
s.add("Sri Lanka");
s.add("India");
s.add("Pakistan");
s.add("China");
s.add("Australia");
s.add("Bhutan");
f.add("London");
f.add("New York");
f.add("Mumbai");
f.add("sydeny");
f.clear();
f.addAll(s);
If you want to add elements in f to s following will work
s.addAll(f);
That's all. Why you use for loop in your code?
You can try this out:
First add all elements from s to f
f.addAll(s);
Then retain only elements in f that are present in s
f.retainAll(s);
I'm trying to read a CSV file into a list of lists (of strings), pass it around for getting some data from a database, build a new list of lists of new data, then pass that list of lists so it can be written to a new CSV file. I've looked all over, and I can't seem to find an example on how to do it.
I'd rather not use simple arrays since the files will vary in size and I won't know what to use for the dimensions of the arrays. I have no issues dealing with the files. I'm just not sure how to deal with the list of lists.
Most of the examples I've found will create multi-dimensional arrays or perform actions inside the loop that's reading the data from the file. I know I can do that, but I want to write object-oriented code. If you could provide some example code or point me to a reference, that would be great.
ArrayList<ArrayList<String>> listOLists = new ArrayList<ArrayList<String>>();
ArrayList<String> singleList = new ArrayList<String>();
singleList.add("hello");
singleList.add("world");
listOLists.add(singleList);
ArrayList<String> anotherList = new ArrayList<String>();
anotherList.add("this is another list");
listOLists.add(anotherList);
Here's an example that reads a list of CSV strings into a list of lists and then loops through that list of lists and prints the CSV strings back out to the console.
import java.util.ArrayList;
import java.util.List;
public class ListExample
{
public static void main(final String[] args)
{
//sample CSV strings...pretend they came from a file
String[] csvStrings = new String[] {
"abc,def,ghi,jkl,mno",
"pqr,stu,vwx,yz",
"123,345,678,90"
};
List<List<String>> csvList = new ArrayList<List<String>>();
//pretend you're looping through lines in a file here
for(String line : csvStrings)
{
String[] linePieces = line.split(",");
List<String> csvPieces = new ArrayList<String>(linePieces.length);
for(String piece : linePieces)
{
csvPieces.add(piece);
}
csvList.add(csvPieces);
}
//write the CSV back out to the console
for(List<String> csv : csvList)
{
//dumb logic to place the commas correctly
if(!csv.isEmpty())
{
System.out.print(csv.get(0));
for(int i=1; i < csv.size(); i++)
{
System.out.print("," + csv.get(i));
}
}
System.out.print("\n");
}
}
}
Pretty straightforward I think. Just a couple points to notice:
I recommend using "List" instead of "ArrayList" on the left side when creating list objects. It's better to pass around the interface "List" because then if later you need to change to using something like Vector (e.g. you now need synchronized lists), you only need to change the line with the "new" statement. No matter what implementation of list you use, e.g. Vector or ArrayList, you still always just pass around List<String>.
In the ArrayList constructor, you can leave the list empty and it will default to a certain size and then grow dynamically as needed. But if you know how big your list might be, you can sometimes save some performance. For instance, if you knew there were always going to be 500 lines in your file, then you could do:
List<List<String>> csvList = new ArrayList<List<String>>(500);
That way you would never waste processing time waiting for your list to grow dynamically grow. This is why I pass "linePieces.length" to the constructor. Not usually a big deal, but helpful sometimes.
Hope that helps!
If you are really like to know that handle CSV files perfectly in Java, it's not good to try to implement CSV reader/writer by yourself. Check below out.
http://opencsv.sourceforge.net/
When your CSV document includes double-quotes or newlines, you will face difficulties.
To learn object-oriented approach at first, seeing other implementation (by Java) will help you. And I think it's not good way to manage one row in a List. CSV doesn't allow you to have difference column size.
The example provided by #tster shows how to create a list of list. I will provide an example for iterating over such a list.
Iterator<List<String>> iter = listOlist.iterator();
while(iter.hasNext()){
Iterator<String> siter = iter.next().iterator();
while(siter.hasNext()){
String s = siter.next();
System.out.println(s);
}
}
Something like this would work for reading:
String filename = "something.csv";
BufferedReader input = null;
List<List<String>> csvData = new ArrayList<List<String>>();
try
{
input = new BufferedReader(new FileReader(filename));
String line = null;
while (( line = input.readLine()) != null)
{
String[] data = line.split(",");
csvData.add(Arrays.toList(data));
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
if(input != null)
{
input.close();
}
}
I'd second what xrath said - you're better off using an existing library to handle reading / writing CSV.
If you do plan on rolling your own framework, I'd also suggest not using List<List<String>> as your implementation - you'd probably be better off implementing CSVDocument and CSVRow classes (that may internally uses a List<CSVRow> or List<String> respectively), though for users, only expose an immutable List or an array.
Simply using List<List<String>> leaves too many unchecked edge cases and relying on implementation details - like, are headers stored separately from the data? or are they in the first row of the List<List<String>>? What if I want to access data by column header from the row rather than by index?
what happens when you call things like :
// reads CSV data, 5 rows, 5 columns
List<List<String>> csvData = readCSVData();
csvData.get(1).add("extraDataAfterColumn");
// now row 1 has a value in (nonexistant) column 6
csvData.get(2).remove(3);
// values in columns 4 and 5 moved to columns 3 and 4,
// attempting to access column 5 now throws an IndexOutOfBoundsException.
You could attempt to validate all this when writing out the CSV file, and this may work in some cases... but in others, you'll be alerting the user of an exception far away from where the erroneous change was made, resulting in difficult debugging.
public class TEst {
public static void main(String[] args) {
List<Integer> ls=new ArrayList<>();
ls.add(1);
ls.add(2);
List<Integer> ls1=new ArrayList<>();
ls1.add(3);
ls1.add(4);
List<List<Integer>> ls2=new ArrayList<>();
ls2.add(ls);
ls2.add(ls1);
List<List<List<Integer>>> ls3=new ArrayList<>();
ls3.add(ls2);
methodRecursion(ls3);
}
private static void methodRecursion(List ls3) {
for(Object ls4:ls3)
{
if(ls4 instanceof List)
{
methodRecursion((List)ls4);
}else {
System.out.print(ls4);
}
}
}
}
Also this is an example of how to print List of List using advanced for loop:
public static void main(String[] args){
int[] a={1,3, 7, 8, 3, 9, 2, 4, 10};
List<List<Integer>> triplets;
triplets=sumOfThreeNaive(a, 13);
for (List<Integer> list : triplets){
for (int triplet: list){
System.out.print(triplet+" ");
}
System.out.println();
}
}