ArrayList different method's scope - java

I have a problem with the code below. I'm getting different results base on where the line list = new ArrayList<InClass>(); is declared. In place //B but everything works fine when I add it to //A and I cannot understand the difference. Here is the code:
import java.util.*;
import java.io.*;
public class ArrayListOne {
private ArrayList<InClass> list;
private InClass in;
public static void main(String args[]) {
ArrayListOne a = new ArrayListOne();
a.readFile();
}
public void readFile() {
//A
/**
* adding "list = new ArrayList<InClass>();"
* getting all 4 lines of test.txt
*/
try {
File file = new File("test.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
while ((line = reader.readLine()) != null) {
assignToObject(line);
}
} catch (Exception ex) {
ex.printStackTrace();
}
readObject();
}
public void assignToObject(String s) {
//B
/**
* adding "list = new ArrayList<InClass>();"
* getting just last line of test.txt
*/
InClass n = new InClass(s);
list.add(n);
System.out.println(list.size());
}
public void readObject() {
for (int i=0; i<list.size(); i++) {
in = list.get(i);
System.out.println(in.stTest);
}
}
//inner class
public class InClass {
String stTest;
public InClass(String s) {
stTest = s;
}
}
}
the test.txt has 3 lines. in //A, I'm getting all three lines (what I want) but in //B I just get the last line.

It's easier to see the difference if you "inline" assignToObject() by copy-pasting the contents of assignToObject() to the proper place in readFile():
public void readFile() {
// B
// list = new ArrayList<InClass>();
try {
File file = new File("test.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
while ((line = reader.readLine()) != null) {
// Here is where assignToObject() was //
// B
// list = new ArrayList<InClass>();
InClass n = new InClass(line);
list.add(n);
System.out.println(list.size());
}
} catch (Exception ex) {
ex.printStackTrace();
}
readObject();
}
Now think about if you put list = new ArrayList<InClass>() in A and B.
If you declare list = new ArrayList<InClass>() at A (i.e. inside readFile()), the statement will be executed once -- when readFile() is called in main(). So you'll end up with one ArrayList containing everything you need.
However, if you declare list = new ArrayList<InClass>() at B (i.e. inside assignToObject()), you'll get a new list for every line you read (i.e. every time you call assignToObject()). This means that every iteration you'll end up with a new ArrayList that only contains the most recently read line. The ArrayList containing the previous line was thrown away, as the reference that used to point to it now points to a new object.

Related

sorting files using multithreading in java

I was given an assignment to write all ordered contents of given files into a result.txt. At first, the filenames are split into different Arraylists where each file contains a label in a format #n/N where N is the total number of files. e.g.
British explorer James Clark Ross led the first
expedition to reach the north magnetic pole
#001/004
from a file 1831-06-01.txt
The problem with my code is that it has written in order 1,4,2,3 respectively. However, the result must be in order 1,2,3,4. This may be due to a lack of synchronization. Nonetheless, I am still struggling to fix the problem.
This is my code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
class PopThread implements Runnable {
ArrayList<String> fileList;
public PopThread(ArrayList<String> fileList) {
this.fileList = fileList;
}
#Override
public void run() {
//System.out.println("running\n");
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
long startTime = System.nanoTime();
System.out.println("fileList: " + fileList);
ArrayList<String> sortedFileList = sortFiles(fileList);
File resultFile = new File("result.txt");
for (String filename : sortedFileList) {
Writer w1 = new Writer(filename, resultFile);
Thread t = new Thread(w1);
t.setPriority(Thread.MAX_PRIORITY);
t.start();
}
long stopTime = System.nanoTime();
//System.out.println("Total execution time: " + (stopTime - startTime));
}
public ArrayList<String> readFiles(String filename) {
ArrayList<String> list = new ArrayList<String>();
try {
File myObj = new File(filename);
Scanner s = new Scanner(myObj);
while (s.hasNext()) {
list.add(s.next());
}
s.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return list;
}
public int getNumber(String filename) {
String lastLine = "";
String sCurrentLine;
int identifier_integer = -1;
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
while ((sCurrentLine = br.readLine()) != null) {
lastLine = sCurrentLine;
}
String identifier_number = lastLine.substring(1,4);
identifier_integer = Integer.parseInt(identifier_number);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return identifier_integer;
}
public ArrayList<String> sortFiles(ArrayList<String> listFileName) {
int i = listFileName.size();
boolean sorted = false;
while ( (i > 1) && (!(sorted)) ) {
sorted = true;
for (int j = 1; j < i; j++) {
if ( getNumber(listFileName.get(j-1)) > getNumber(listFileName.get(j)) ) {
String temp = listFileName.get(j-1);
listFileName.set(j-1, listFileName.get(j));
listFileName.set(j, temp);
sorted = false;
}
}
i--;
}
return listFileName;
}
}
class Writer implements Runnable {
String filename;
File resultFile;
public Writer(String filename, File resultFile) {
this.filename = filename;
this.resultFile = resultFile;
}
#Override
public void run() {
String content;
content = readFromFile(filename);
writeToFile(resultFile, content);
}
private static void writeToFile(File resultFile, String content) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile, true));
writer.write(content);
//writer.write("file content written");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
static String readFromFile(String filename) {
StringBuffer content = new StringBuffer();
try {
String text;
BufferedReader reader = new BufferedReader(new FileReader(filename));
while ((text = reader.readLine()) != null) {
content.append(text);
content.append("\n");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return content.toString();
}
}
public class q4 {
public static void main(String[] args) {
ArrayList<String> filesOne = new ArrayList<String>();
filesOne.add("1831-06-01.txt");
filesOne.add("2003-08-27.txt");
ArrayList<String> filesTwo = new ArrayList<String>();
filesTwo.add("1961-04-12.txt");
filesTwo.add("1972-12-11.txt");
PopThread popRunnableOne = new PopThread(filesOne);
PopThread popRunnableTwo = new PopThread(filesTwo);
Thread threadOne = new Thread(popRunnableOne);
Thread threadTwo = new Thread(popRunnableTwo);
threadOne.start();
threadTwo.start();
try {
threadOne.join();
threadTwo.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
( NOTE: The class q4 cannot be altered)
This assignment is horrible. You have my sympathy.
Your two threads will have to communicate with each other. Each thread will have to know, what is the filename that the other thread wants to output next. And, they will have to take turns. Each thread needs to loop:
While the date on my next file is less than or equal to the date on the other thread's next file, output my next file,
Tell the other thread, "it's your turn,"
If I have no more files, then exit (return from the run() method), otherwise, wait for the other thread to tell me it's my turn again,
Go back to step 1.
Having to take turns is the worst part of the assignment. Any time you find yourself needing to make threads take turns doing something—any time you need to make threads do things in a particular order—that's a clear sign that all of the things should be done by a single thread.
The only way threads can communicate is through shared variables. Your instructor has done you a huge disservice by telling you not to modify the q4 class. That prevents you from passing any shared objects in to your PopThread implementation through its constructor.
The only other way your two threads can share any variables is by making the variables static. Forcing you to use static is the second worst part of the assignment. If you go on to study software engineering, you will learn that static is an anti-pattern. Programs that use static variables are brittle (i.e., hard to modify), and they are hard to test.
Forcing you to use static variables also will make your threads do extra work to figure out who is who. Normally, I would do something like this so that each thread would automatically know which state is its own, and which belongs to the other guy:
class SharedState { ... }
class PopThread {
public PopThread(
SharedState myState,
SharedState otherThreadState,
ArrayList<String> fileList
) {
this.myState = myState;
this.otherGuyState = otherThreadState;
this.fileList = fileList;
...initialize this.myState...
}
...
}
class q4 {
public static void main(String[] args) {
SharedState stateOne = new SharedState();
SharedState stateTwo = new SharedState();
PopThread popRunnableOne = new PopThread(stateOne, stateTwo, filesOne);
PopThread popRunnableTwo = new PopThread(stateTwo, stateOne, filesTwo);
...
}
}
The best way I can think of with static variables would be to have an array of two SharedState, and have the threads use an AtomicInteger to each assign themself one of the two array slots:
class PopThread {
static SharedState[] state = new SharedState [2];
static AtomicInteger nextStateIndex = new AtomicInteger(0);
public PopThread(
SharedState myState,
SharedState otherThreadState,
ArrayList<String> fileList
) {
myStateIndex = nextStateIndex.getAndIncrement();
otherGuysStateIndex = myStateIndex ^ 1;
this.fileList = fileList;
...initialize state[myStateIndex]...
}
...
}

creating multiple arraylists from a file in java

i am new to java so i need help...
i have a file which contains:-
Model
A
T
ENMDL
Model
A
T
ENMDL
.... repeat multiple times and i need to make a program which separate them and store them in different arraylists.
can anyone help..
public ArrayList<String> GetAllFile(String File) throws IOException
{
FileReader fr=new FileReader(File);
BufferedReader br=new BufferedReader(fr);
String rowData;
ArrayList<String> allFile = new ArrayList<String>();
while((rowData=br.readLine())!=null)
if(rowData.startsWith("MODEL"))
allFile.add(rowData);
fr.close();
return allFile;
}
}
Change your return type.
public static List<List<String>> fileToArrayList(String fileName) {
Create the outer container.
List<List<String>> allFile = new ArrayList<>();
Then outside of your loop.
List<String> modelLines = new ArrayList<>();
Then the condition inside of your loop should be.
if(rowData.startsWith("Model")){
modelLines = new ArrayList<>();
allFile.add(modelLines);
} else{
modelLines.add(rowData);
}
Here is an solution that might suit you:
public class FileToArrayList {
public static void main(String[] args) {
// Get the file as an List.
List<String> fileAsList = FileToArrayList.fileToArrayList("SomeFile.txt");
// Print the lines.
for (String oneLine : fileAsList) {
System.out.println(oneLine);
}
}
public static List<String> fileToArrayList(String fileName) {
// Container for the lines.
List<String> lines = new ArrayList<>();
// Try with resources, it will close it automatically afterwards.
try(FileReader fr = new FileReader(new File(fileName))) {
BufferedReader br = new BufferedReader(fr);
String line;
// line = br.readLine() is an expression which will return line, therefore
// we can check if that expression is not null, because
// when its null, we reached EOF (end of file)
while((line = br.readLine()) != null) {
lines.add(line);
}
} catch(IOException e) {
e.printStackTrace();
}
return lines;
}
}

How to read from textfile and pass values to another class Java?

I'm making a Java program that needs to read info from a text file and then store it in an array and pass it to another class when called. My issue is that I can't seem to call it due to the IOException needed in the file reader class.
This is the main class that is supposed to call the fileReader.
public class window {
public static void main(String[] args){
String[] people = readFromText.read("people.txt");
}
}
File Reader Class
public class readFromText{
public static String[] read(String textFile) throws IOException {
BufferedReader inputFile = new BufferedReader(new
FileReader(textFile));
String[] array = new String[10];
String line = inputFile.readLine().toString();
int cnt = 0;
while (line!=null){
array[cnt] = line;
line = inputFile.readLine().toString();
cnt++;
}
inputFile.close();
return array;
}
}
Is it possible to do this, this way?
Firstly your code is not correct. You can not return the String[] array for the function need String[][].
Secondly for problem about exception you just need to catch it in your main class.
try {
String[] people = readFromText.read("people.txt");
} catch (IOException e) {
e.printStackTrace();
}

How can I get what I'm reading in from a file to an output file

I'm able to pull out the 20 names randomly but how do I store them in an output file rather than displaying them to the screen? I tried filewriter but couldn't get it to work.
public class Assignment2 {
public static void main(String[] args) throws IOException {
// Read in the file into a list of strings
BufferedReader reader = new BufferedReader(new FileReader("textfile.txt"));
//BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
List<String> lines = new ArrayList<String>();
String line = reader.readLine();
while( line != null ) {
lines.add(line);
line = reader.readLine();
}
// Choose a random one from the list
Random r = new Random();
FileWriter letters = new FileWriter("out.txt");
for (int i = 0; i < 20; i++) {
int rowNum = r.nextInt(lines.size ());
System.out.println(lines.get(rowNum));
}
}
}
System.out is a PrintStream (javadoc) and not a Writer (javadoc) so the api to access it will be different, you can't replace one by the other. The Writer is some how a lower level abstraction.
But it is easy to create a PrintStream that output a a file and use it as replacement of System.out:
PrintStreasm out = new PrintStream("out.txt");
// you can event assign System.out to out.
// out = System.out;
for (int i = 0; i < 20; i++) {
int rowNum = r.nextInt(lines.size ());
out.println(lines.get(rowNum));
}
out.close()
PS: don't forget to closed any file you open (auto closable functionality of Java 7 is even better)
PSS: I assume you are learning Java, I can't recommend enough that you have a look to at the Java I/O stream apis.
I am using a convince method to write to the file from the library commons.io-2.4, code is also available on github
this example demonstrate how to read and write String lines to a file
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
/**
* Created by Pankaj Nimgade on 10-02-2016.
*/
public class WriteFile {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add("somename_" + i);
}
File file = new File("file.txt");
try {
// FileUtils.writeLines(file, list);
ArrayList<String> strings = (ArrayList<String>) FileUtils.readLines(file);
ArrayList<Name> names = new ArrayList<>();
for (String single:strings) {
names.add(new Name(single));
if (names.size() == 20) {
break;
}
}
for (Name single_name:names) {
System.out.println(single_name.getName());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Name {
String name;
public Name(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object obj) {
return this.name.equalsIgnoreCase(((Name) obj).getName());
}
}
output, this will be inside file.txt
somename_0
somename_1
somename_2
somename_3
somename_4
somename_5
somename_6
somename_7
somename_8
somename_9
somename_10
somename_11
somename_12
somename_13
somename_14
somename_15
somename_16
somename_17
somename_18
somename_19

A Producer-Consumer implemented using java threads writes only half the data to file

Hello I have a problem wherein I have to read a huge csv file. remove first field from it, then store only unique values to a file. I have written a program using threads which implements producer-consumer pattern.
Class CSVLineStripper does what the name suggests. Takes a line out of csv, removes first field from every line and adds it to a queue. CSVLineProcessor then takes that field stores all one by one in an arraylist and checks if fields are unique so only uniques are stored. Arraylist is only used for reference. every unique field is written to a file.
Now what is happening is that all fields are stripped correctly. I run about 3000 lines it's all correct. When I start the program for all lines, which are around 7,00,000 + lines, i get incomplete records, about 1000 unique are not taken. Every field is enclosed in double-quotes. What is weird is that the last field in the file that is generated is an incomplete word and ending double quote is missing. Why is this happening?
import java.util.*;
import java.io.*;
class CSVData
{
Queue <String> refererHosts = new LinkedList <String> ();
Queue <String> uniqueReferers = new LinkedList <String> (); // final writable queue of unique referers
private int finished = 0;
private int safety = 100;
private String line = "";
public CSVData(){}
public synchronized String getCSVLine() throws InterruptedException{
int i = 0;
while(refererHosts.isEmpty()){
if(i < safety){
wait(10);
}else{
return null;
}
i++;
}
finished = 0;
line = refererHosts.poll();
return line;
}
public synchronized void putCSVLine(String CSVLine){
if(finished == 0){
refererHosts.add(CSVLine);
this.notifyAll();
}
}
}
class CSVLineStripper implements Runnable //Producer
{
private CSVData cd;
private BufferedReader csv;
public CSVLineStripper(CSVData cd, BufferedReader csv){ // CONSTRUCTOR
this.cd = cd;
this.csv = csv;
}
public void run() {
System.out.println("Producer running");
String line = "";
String referer = "";
String [] CSVLineFields;
int limit = 700000;
int lineCount = 1;
try {
while((line = csv.readLine()) != null){
CSVLineFields = line.split(",");
referer = CSVLineFields[0];
cd.putCSVLine(referer);
lineCount++;
if(lineCount >= limit){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("<<<<<< PRODUCER FINISHED >>>>>>>");
}
private String printString(String [] str){
String string = "";
for(String s: str){
string = string + " "+s;
}
return string;
}
}
class CSVLineProcessor implements Runnable
{
private CSVData cd;
private FileWriter fw = null;
private BufferedWriter bw = null;
public CSVLineProcessor(CSVData cd, BufferedReader bufferedReader){ // CONSTRUCTOR
this.cd = cd;
try {
this.fw = new FileWriter("unique_referer_dump.txt");
} catch (IOException e) {
e.printStackTrace();
}
this.bw = new BufferedWriter(fw);
}
public void run() {
System.out.println("Consumer Started");
String CSVLine = "";
int safety = 10000;
ArrayList <String> list = new ArrayList <String> ();
while(CSVLine != null || safety <= 10000){
try {
CSVLine = cd.getCSVLine();
if(!list.contains(CSVLine)){
list.add(CSVLine);
this.CSVDataWriter(CSVLine);
}
} catch (Exception e) {
e.printStackTrace();
}
if(CSVLine == null){
break;
}else{
safety++;
}
}
System.out.println("<<<<<< CONSUMER FINISHED >>>>>>>");
System.out.println("Unique referers found in 30000 records "+list.size());
}
private void CSVDataWriter(String referer){
try {
bw.write(referer+"\n");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class RefererCheck2
{
public static void main(String [] args) throws InterruptedException
{
String pathToCSV = "/home/shantanu/DEV_DOCS/Contextual_Work/excite_domain_kw_site_wise_click_rev2.csv";
CSVResourceHandler csvResHandler = new CSVResourceHandler(pathToCSV);
CSVData cd = new CSVData();
CSVLineProcessor consumer = new CSVLineProcessor(cd, csvResHandler.getCSVFileHandler());
CSVLineStripper producer = new CSVLineStripper(cd, csvResHandler.getCSVFileHandler());
Thread consumerThread = new Thread(consumer);
Thread producerThread = new Thread(producer);
producerThread.start();
consumerThread.start();
}
}
This is how a sample input is:
"xyz.abc.com","4432"."clothing and gifts","true"
"pqr.stu.com","9537"."science and culture","false"
"0.stu.com","542331"."education, studies","false"
"m.dash.com","677665"."technology, gadgets","false"
Producer stores in queue:
"xyz.abc.com"
"pqr.stu.com"
"0.stu.com"
"m.dash.com"
Consumer stores uniques in the file, but after opening file contents one would see
"xyz.abc.com"
"pqr.stu.com"
"0.st
Couple things, you are breaking after 700k, not 7m, also you are not flushing your buffered writer, so the last stuff you could be incomplete, add flush at end and close all your resources. Debugger is a good idea :)

Categories

Resources