Java arraylist of different object class - java

i have an issue with the understanding the arraylist which contain the objects from different classes. I have 6 objects. All of objects have 2 attributes in common.(ID,Type)
Every object has its own attributes. I created mainObject class with 2 atr (ID,Type). The other objects extends the mainObject so they have
class mainClass{
this.id=id;
this.type=type;
}
class extendedClass extends mainClass{
super(ID,Type);
this.atr1=atr1;
}
class extendedClass2 extends mainClass{
super(ID,type);
this.atr2=atr2;
this.atr3=atr3;
}
I read the informations from file.
FileInputStream fstream = new FileInputStream("data.txt");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
String s[] = strLine.split("\\|");
mainClass myObj = new mainClass(s[0], s[1]);
ArrayList<mainClass> items = new ArrayList<mainClass>();
items.add(myObj);
I need all objects to be readed from file line by line and store them in the array list.
How should i do this? I tried the ArrayList<Object> list = new ArrayList<Object>, but its not working. The point is read all the objects from file, sort them due to chosen attribute(id,type).

You are correct that you need a list of mainClass:
ArrayList<mainClass> items = new ArrayList<mainClass>();
However you should put this line before the while loop, not inside it.
ArrayList<mainClass> items = new ArrayList<mainClass>();
while ((strLine = br.readLine()) != null) {
// etc...
items.add(myObj);
}

Related

Only add unique elements to arraylist in Java

I am currently writing a java program that takes data from a text file and adds to to an array list. My problem is, that every time I run the program, the arraylist keeps updating and has duplicate elements - I would like each element to only appear once.
`
BufferedReader br = new BufferedReader(new FileReader("s.txt"));
for (String line = br.readLine(); line != null; line = br.readLine()) {
if(!listID.contains(Integer.parseInt(line))){
listID.add(Integer.parseInt(line));
}
for(int i=0;i<listID.size();i++){
// do stuff
}
`
I have tried to use does not contain but it isnt working.
Does this work for you?
Set<Integer> set = new HashSet();
BufferedReader br = new BufferedReader(new FileReader("s.txt"));
for (String line = br.readLine(); line != null; line = br.readLine()) {
set.add(Integer.parseInt(line));
for(int i=0;i<listID.size();i++){
// do stuff
}
}

Parse CSV file to a generic class - Java generics

I'm trying to build up a generic method that parses a CSV file into an Object.
I think I'm quite close to reach the objective but I'm a bit stuck with java generics, I'm still learning it.
Now I'm stuck on my while cycle where I create the objects. I'm using jCSV to do the parsing for me. I'm following their documentation tutorial here.
I can't figure out how to set the beanClass bc = it.next(); because beanClass does not exist as a class on my project, compilation error: cannot find symbol - class beanClass
How can I fix this?
I know I could simply do a List<?> beanClassList = csvFileReader.readAll();
but the problem is that on the first line of each CSV file I've the class name to where that data belongs to. I get this exception, which makes sense:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "Car"
My CSV files are something like this:
ClassName
value,value,value,value,value
value,value,value,value,value
...
Here's my code:
public String importFromCsvFile(File f) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException
{
FileReader fr = new FileReader(f);
BufferedReader buffReader = new BufferedReader(fr);
String className = buffReader.readLine();
buffReader.close();
//Java reflection to get the Class Object.
Class beanClass = Class.forName("model." + className);
Object beanObject = beanClass.newInstance();
Reader reader = new FileReader(f);
ValueProcessorProvider provider = new ValueProcessorProvider();
CSVEntryParser<?> entryParser = new AnnotationEntryParser<>(beanClass, provider);
CSVReader<?> csvFileReader= new CSVReaderBuilder<>(reader).entryParser((CSVEntryParser<Object>) entryParser).build();
Iterator<?> it = csvFileReader.iterator();
while (it.hasNext()) {
beanClass bc = it.next(); // here is the compilation error
}
}
Here's a CSV file example:
Car
1,BMW,Z3,2000,20-AC-57
2,Mercedes,C4,2010,23-32-VJ
3,Alfa Romeo,A3,1992,XX-XX-XX
you are nearly there.
public String importFromCsvFile(File f) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException
{
FileReader fr = new FileReader(f);
BufferedReader buffReader = new BufferedReader(fr);
String className = buffReader.readLine();
buffReader.close(); // you can also not close it and use buffReader as your reader for the CSV
//Java reflection to get the Class Object.
Class beanClass = Class.forName("model." + className);
Object beanObject = beanClass.newInstance(); // this is never needed
Reader reader = new FileReader(f); // use buffReader instead of creating a new one
ValueProcessorProvider provider = new ValueProcessorProvider();
CSVEntryParser<?> entryParser = new AnnotationEntryParser<>(beanClass, provider);
CSVReader<?> csvFileReader= new CSVReaderBuilder<>(reader).entryParser((CSVEntryParser<Object>) entryParser).build();
Iterator<?> it = csvFileReader.iterator();
while (it.hasNext()) {
Object obj = it.next(); // obj is an instance of Car with your data
boolean isCar = obj instanceof Car; // will be true
}
}
Because you are using , as separator you should consider using UK_DEFAULT as Strategy for the Reader or defining your own (the default separator is ;).
You should also either continue using the BufferedReader or specify skipHeader in the Strategy - else you Car will be treated as entry which is probably not what you want.
As per your comments Please have a look at sample code that reads data from CSV file and store in a map as key-value pair.
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
BufferedReader reader = new BufferedReader(new FileReader(new File("resources/abc.csv")));
String header = reader.readLine();
String[] keys = header.split(",");
String line = null;
while ((line = reader.readLine()) != null) {
Map<String, String> map = new HashMap<String, String>();
String[] values = line.split(",");
for (int i = 0; i < keys.length; i++) {
map.put(keys[i], values[i]);
}
list.add(map);
}
reader.close();
for(Map<String, String> map:list){
for(String key:map.keySet()){
System.out.println(key+":"+map.get(key));
}
System.out.println();
}
CSV:
ID,NAME,MODEL,YEAR,NUMBER
1,BMW,Z3,2000,20-AC-57
2,Mercedes,C4,2010,23-32-VJ
3,Alfa Romeo,A3,1992,XX-XX-XX
With generics, types are specified at compile time (and checked by the compiler). In your case, types are only specified in the CSV file and thus unknown at compile time. So generics is not a tool you can use in this case.
What exactly would you want to accomplish with generics? What would you like the compiler to check?
What you can do is create an instance of the class (you will need a full name including package) using Class.forName(name).newInstance() and use reflection to set some properties. But at compile time you'll only know the result is an Object.

Retrieving ArrayList information from a class

I'm new to java and I've just started a project where I need to create a network from a .txt file, where each line in the file is "node1 node2", with a tabulation between nodes. I have created a node class and an edge class which accepts node names as their arguments, and now I'm writing the network class. I'm using Arraylist to store my nodes and interaction (edge) information, but I'm confused as to how I retrieve this information in my main program. Network class as it stands:
import java.io.*;
import java.util.ArrayList;
public class Network {
public ArrayList<String> nodes = new ArrayList<String>();
public ArrayList<String> edges = new ArrayList<String>();
public String filename;
public Network(String f) {
this.filename = f;
FileReader networkinput = null;
try {
networkinput = new FileReader("f");
BufferedReader bufferedReader = new BufferedReader(networkinput);
//reads the argument file in.
String line = null;
while((line = bufferedReader.readLine()) != null) {
edges.add(line); // Adds each line of the file to the array
String delimiter = "\t";
String[] tempnodelist; // Creates an array each loop
tempnodelist = line.split(delimiter);
nodes.add(tempnodelist[0]); // Adds the first node
nodes.add(tempnodelist[1]); // Adds second node to node array.
}
bufferedReader.close();
}
catch (IOException e) {
System.out.println("Read Error!");
}
}
}
As it stands I want this code to accept the file, reach each line and place each node into the arraylist "nodes", and each line (representing an interaction) into the arraylist "edges". I'm unsure how to retrieve this information within the main program to check whether it is doing what I think it is.
Is this code doing what I expect? and how can I retrieve this ArrayList information in the main program?
Please ask any questions if anything is unclear.
Create an instance of the Network class to initialize everything going on in the constructor. Then access the data.
public class TestNetwork {
public static void main(String[] args){
Network network = new Network("file.txt"); <-- create instance
ArrayList<String> nodes = network.nodes; <-- reference the data
ArrayList<String> edges = network.edges;
for (String s : nodes) { <-- traverse data
System.out.println(s); <-- print data
}
for (String s : edges){
System.out.println(s);
}
}
}
Also, another thing wrong I noticed in your constructor is this
networkinput = new FileReader("f"); <-- "f" I don't think is the file path.
You should use this
networkinput = new FileReader(f);
or
networkinput = new FileReader(filename);
Note: Consider what #erzr2 said.
You can call Network.nodes to get the ArrayList, but this is not necessarily advisable, depending on how you use it. More advisably make the ArrayList private and create a getter method that will return the ArrayList and then you can call the method from another class. So something like this:
private ArrayList<String> nodes = new ArrayList<String>();
private ArrayList<String> edges = new ArrayList<String>();
then later have this:
public ArrayList<String> getNodes(){
return nodes;
}

How to read a txt file to an ArrayList of unknown size

How do I read from a txt file with lines of unknown size? For example:
Family1,john,mark,ken,liam
Family2,jo,niamh,liam,adam,apple,joe
Each line has a different number of names. I am able to read in when using object type like
family(parts[0], parts[1], parts[2])
but thats if I know the amout that will be in each. how do I read it in without knowing how many will be in each?
FileReader fr = new FileReader("fam.txt");
BufferedReader br = new BufferedReader(fr);
String fileLines;
String[] parts;
while(br.ready())
{
fileLines = br.readLine();
parts = fileLines.split(",");
.
.
You can use varargs for your family() method to accept the array: family(String ... parts) or just use family(String[] parts).
Personally, I would create a separate class Family and not pollute it with implementation detail about the file format (i.e. that the first item on each line is the family name):
public class Family {
private final List<String> members = new ArrayList<>();
private final String familyName;
public Family(String familyName, Collection<String> members) {
this.familyName = familyName;
this.members.addAll(members);
}
}
Then your loop can be like this:
List<Family> families = new ArrayList<>();
String line;
while ((line = br.readLine()) != null) {
List<String> parts = Arrays.asList(line.split(","));
String familyName = parts.remove(0);
families.add(new Family(familyName, parts));
}
ArrayList<E>: Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null, provides methods to manipulate the size of the array that is used internally to store the list.
Each ArrayList instance has a capacity: size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
So just read your data and add to the array-list using ArrrayList.add(E e) method.
You're struggling since you try to load the data to an String[] which is in turn a plain array. You should use ArrayList that maintains an internal array and it increase its size dynamically.
FileReader fr = new FileReader("fam.txt");
BufferedReader br = new BufferedReader(fr);
String fileLines;
String[] parts;
List<List<String>> data = new ArrayList<>();
while(br.ready()) {
fileLines = br.readLine();
parts = fileLines.split(",");
data.add(Arrays.asList(parts));
//do what you want/need...
}
//do what you want/need...
A better approach would be parsing the data in String[] parts and build an object of some class that will contain the data for your specific case:
public void yourMethod() {
FileReader fr = new FileReader("fam.txt");
BufferedReader br = new BufferedReader(fr);
String fileLines;
String[] parts;
List<Family> familyList = new ArrayList<>();
while(br.ready()) {
fileLines = br.readLine();
parts = fileLines.split(",");
Family family = new Family(parts[0], parts[1], parts[2]);
familyList.add(family);
//do what you want/need...
}
//do what you want/need...
}
My personal preference is to use the Scanner class. You can review the functionality here. With the scanner you can parse the file a line at a time and store those values into a String.
Scanner scan = new Scanner(new File("fam.txt"));
List<String> families = new ArrayList<String>();
while(scan.hasNextLine()){
families.add(scan.nextLine());
}
Then you can do whatever you want with the families in the ArrayList
use a Scanner, that's much easier. You can put both in a while loop
Scanner sc = new Scanner(new File(myFile.txt));
while(sc.hasNextLine()) {
while(sc.hasNextString()) {
String str = sc.nextString();
}
}
This is a simplefied version and it will not work correctly, because you have to store some values in variables for Java to read them correctly. Read the documentation on the Java Scanner to find a more detailed explanation. The Scanner is much easier than what you have been doing

Compare values in two files

I have two files Which should contain the same values between Substring 0 and 10 though not in order. I have Managed to Outprint the values in each file but I need to Know how to Report say id the Value is in the first File and Notin the second file and vice versa. The files are in these formats.
6436346346....Other details
9348734873....Other details
9349839829....Other details
second file
8484545487....Other details
9348734873....Other details
9349839829....Other details
The first record in the first file does not appear in the second file and the first record in the second file does not appear in the first file. I need to be able to report this mismatch in this format:
Record 6436346346 is in the firstfile and not in the secondfile.
Record 8484545487 is in the secondfile and not in the firstfile.
Here is the code I currently have that gives me the required Output from the two files to compare.
package compare.numbers;
import java.io.*;
/**
*
* #author implvcb
*/
public class CompareNumbers {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
File f = new File("C:/Analysis/");
String line;
String line1;
try {
String firstfile = "C:/Analysis/RL001.TXT";
FileInputStream fs = new FileInputStream(firstfile);
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
while ((line = br.readLine()) != null) {
String account = line.substring(0, 10);
System.out.println(account);
}
String secondfile = "C:/Analysis/RL003.TXT";
FileInputStream fs1 = new FileInputStream(secondfile);
BufferedReader br1 = new BufferedReader(new InputStreamReader(fs1));
while ((line1 = br1.readLine()) != null) {
String account1 = line1.substring(0, 10);
System.out.println(account1);
}
} catch (Exception e) {
e.fillInStackTrace();
}
}
}
Please help on how I can effectively achieve this.
I think I needed to say that am new to java and may not grab the ideas that easily but Am trying.
Here is the sample code to do that:
public static void eliminateCommon(String file1, String file2) throws IOException
{
List<String> lines1 = readLines(file1);
List<String> lines2 = readLines(file2);
Iterator<String> linesItr = lines1.iterator();
while (linesItr.hasNext()) {
String checkLine = linesItr.next();
if (lines2.contains(checkLine)) {
linesItr.remove();
lines2.remove(checkLine);
}
}
//now lines1 will contain string that are not present in lines2
//now lines2 will contain string that are not present in lines1
System.out.println(lines1);
System.out.println(lines2);
}
public static List<String> readLines(String fileName) throws IOException
{
List<String> lines = new ArrayList<String>();
FileInputStream fs = new FileInputStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
String line = null;
while ((line = br.readLine()) != null) {
String account = line.substring(0, 10);
lines.add(account);
}
return lines;
}
Perhaps you are looking for something like this
Set<String> set1 = new HashSet<>(FileUtils.readLines(new File("C:/Analysis/RL001.TXT")));
Set<String> set2 = new HashSet<>(FileUtils.readLines(new File("C:/Analysis/RL003.TXT")));
Set<String> onlyInSet1 = new HashSet<>(set1);
onlyInSet1.removeAll(set2);
Set<String> onlyInSet2 = new HashSet<>(set2);
onlyInSet2.removeAll(set1);
If you guarantee that the files will always be the same format, and each readLine() function is going to return a different number, why not have an array of strings, rather than a single string. You can then compare the outcome with greater ease.
Ok, first I would save the two sets of strings in to collections
Set<String> s1 = new HashSet<String>(), s2 = new HashSet<String>();
//...
while ((line = br.readLine()) != null) {
//...
s1.add(line);
}
Then you can compare those sets and find elements that do not appear in both sets. You can find some ideas on how to do that here.
If you need to know the line number as well, you could just create a String wrapper:
class Element {
public String str;
public int lineNr;
public boolean equals(Element compElement) {
return compElement.str.equals(str);
}
}
Then you can just use Set<Element> instead.
Open two Scanners, and :
final TreeSet<Integer> ts1 = new TreeSet<Integer>();
final TreeSet<Integer> ts2 = new TreeSet<Integer>();
while (scan1.hasNextLine() && scan2.hasNexLine) {
ts1.add(Integer.valueOf(scan1.nextLigne().subString(0,10));
ts1.add(Integer.valueOf(scan1.nextLigne().subString(0,10));
}
You can now compare ordered results of the two trees
EDIT
Modified with TreeSet
Put values from each file to two separate HashSets accordingly.
Iterate over one of the HashSets and check whether each value exists in the other HashSet. Report if not.
Iterate over other HashSet and do same thing for this.

Categories