How can I have only one same name in my combobox? There are 2 same name in my fee text file and I want to get the name from fee text file to the combobox. But it display 2 same name.
There are no error in my code and I cannot find out the questions. I think my combobox function got problems. Below is my expected result.
//fee.txt
john|123|0.00
john|456|0.00
//my expected result in combobox
john
//my result
john
john
//filefuncion.java
public class FileFunction {
public static ArrayList getContent(File f) {
ArrayList ls = null;
try (BufferedReader in = new BufferedReader(new FileReader(f));) {
String line;
ls = new ArrayList();
/*while ((line = in.readLine()) != null) {
ls.add(line);
}*/
while ((line = in.readLine()) != null) {
if (line.trim().length() > 0) {
ls.add(line);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ls;
}
//my code
private void combobox(){
File file = new File("fee.txt");
ArrayList al = FileFunction.getContent(file);
for (Object obj : al) {
String newobj = obj.toString();
String text[] = newobj.split("\\|");
String name = text[0];
String status = text[2];
if(status.equals("0.00")){
comboboxResident.addItem(name);
}
}
}
First, use generics to ensure a stronger type-checking and reduce bugs due to incorrect types. Write something like ArrayList<String> instead of plain ArrayList.
If you want to remove duplicate elements in an ArrayList instance, the most convenient way is to build a Set (which is a class under the Collection framework) and convert it back to ArrayList (if you need to).
For example, suppose you have an ArrayList instance, then you may write
ArrayList<String> list = ...
LinkedHashSet<String> set = new LinkedHashSet<>(list);
Just iterate through set will do. Or you can convert it back to a list by ArrayList<String> newList = new ArrayList<>(set);.
A LinkedHashSet implements the Set interface and does not contain duplicate elements. It also has predictable iteration order. If you want to further sort you elements, try a TreeSet instead.
Related
I am reading a txt file and store the data in a hashtable, but I couldn't get the correct output. the txt file like this (part) attached image
this is part of my data
And I want to store the column 1 and column 2 as the key(String type) in hashtable, and column 3 and column 4 as the value (ArrayList type) in hashtable.
My code below:
private Hashtable<String, ArrayList<String[]>> readData() throws Exception {
BufferedReader br = new BufferedReader (new FileReader("MyGridWorld.txt"));
br.readLine();
ArrayList<String[]> value = new ArrayList<String[]>();
String[] probDes = new String[2];
String key = "";
//read file line by line
String line = null;
while ((line = br.readLine()) != null && !line.equals(";;")) {
//System.out.println("line ="+line);
String source;
String action;
//split by tab
String [] splited = line.split("\\t");
source = splited[0];
action = splited[1];
key = source+","+action;
probDes[0] = splited[2];
probDes[1] = splited[3];
value.add(probDes);
hashTableForWorld.put(key, value);
System.out.println("hash table is like this:" +hashTableForWorld);
}
br.close();
return hashTableForWorld;
}
The output looks like this:
it's a very long long line
I think maybe the hashtable is broken, but I don't know why. Thank you for reading my problem.
The first thing we need to establish is that you have a really obvious XY-Problem, in that "what you need to do" and "how you're trying to solve it" are completely at odds with each other.
So let's go back to the original problem and try to work out what we need first.
As best as I can determine, source and action are connected, in that they represent queryable "keys" to your data structure, and probability, destination, and reward are queryable "outcomes" in your data structure. So we'll start by creating objects to represent those two concepts:
public class SourceAction implements Comparable<SourceAction>{
public final String source;
public final String action;
public SourceAction() {
this("", "");
}
public SourceAction(String source, String action) {
this.source = source;
this.action = action;
}
public int compareTo(SourceAction sa) {
int comp = source.compareTo(sa.source);
if(comp != 0) return comp;
return action.compareto(sa.action);
}
public boolean equals(SourceAction sa) {
return source.equals(sa.source) && action.equals(sa.action);
}
public String toString() {
return source + ',' + action;
}
}
public class Outcome {
public String probability; //You can use double if you've written code to parse the probability
public String destination;
public String reward; //you can use double if you're written code to parse the reward
public Outcome() {
this("", "", "");
}
public Outcome(String probability, String destination, String reward) {
this.probability = probability;
this.destination = destination;
this.reward = reward;
}
public boolean equals(Outcome o) {
return probability.equals(o.probability) && destination.equals(o.destination) && reward.equals(o.reward);
public String toString() {
return probability + ',' + destination + ',' + reward;
}
}
So then, given these objects, what sort of Data Structure can properly encapsulate the relationship between these objects, given that a SourceAction seems to have a One-To-Many relationship to Outcome objects? My suggestion is that a Map<SourceAction, List<Outcome>> represents this relationship.
private Map<SourceAction, List<Outcome>> readData() throws Exception {
It is possible to use a Hash Table (in this case, HashMap) to contain these objects, but I'm trying to keep the code as simple as possible, so we're going to stick to the more generic interface.
Then, we can reuse the logic you used in your original code to insert values into this data structure, with a few tweaks.
private Map<SourceAction, List<Outcome>> readData() {
//We're using a try-with-resources block to eliminate the later call to close the reader
try (BufferedReader br = new BufferedReader (new FileReader("MyGridWorld.txt"))) {
br.readLine();//Skip the first line because it's just a header
//I'm using a TreeMap because that makes the implementation simpler. If you absolutely
//need to use a HashMap, then make sure you implement a hash() function for SourceAction
Map<SourceAction, List<Outcome>> dataStructure = new TreeMap<>();
//read file line by line
String line = null;
while ((line = br.readLine()) != null && !line.equals(";;")) {
//split by tab
String [] splited = line.split("\\t");
SourceAction sourceAction = new SourceAction(splited[0], splited[1]);
Outcome outcome = new Outcome(splited[2], splited[3], splited[4]);
if(dataStructure.contains(sourceAction)) {
//Entry already found; we're just going to add this outcome to the already
//existing list.
dataStructure.get(sourceAction).add(outcome);
} else {
List<Outcome> outcomes = new ArrayList<>();
outcomes.add(outcome);
dataStructure.put(sourceAction, outcomes);
}
}
} catch (IOException e) {//Do whatever, or rethrow the exception}
return dataStructure;
}
Then, if you want to query for all the outcomes associated with a given source + action, you need only construct a SourceAction object and query the Map for it.
Map<SourceAction, List<Outcome>> actionMap = readData();
List<Outcome> outcomes = actionMap.get(new SourceAction("(1,1)", "Up"));
assert(outcomes != null);
assert(outcomes.size() == 3);
assert(outcomes.get(0).equals(new Outcome("0.8", "(1,2)", "-0.04")));
assert(outcomes.get(1).equals(new Outcome("0.1", "(2,1)", "-0.04")));
assert(outcomes.get(2).equals(new Outcome("0.1", "(1,1)", "-0.04")));
This should yield the functionality you need for your problem.
You should change your logic for adding to your hashtable to check for the key you create. If the key exists, then grab your array list of arrays that it maps to and add your array to it. Currently you will overwrite the data.
Try this
if(hashTableForWorld.containsKey(key))
{
value = hashTableForWorld.get(key);
value.add(probDes);
hashTableForWorld.put(key, value);
}
else
{
value = new ArrayList<String[]>();
value.add(probDes);
hashTableForWorld.put(key, value);
}
Then to print the contents try something like this
for (Map.Entry<String, ArrayList<String[]>> entry : hashTableForWorld.entrySet()) {
String key = entry.getKey();
ArrayList<String[]> value = entry.getValue();
System.out.println ("Key: " + key + " Value: ");
for(int i = 0; i < value.size(); i++)
{
System.out.print("Array " + i + ": ");
for(String val : value.get(i))
System.out.print(val + " :: ")
System.out.println();
}
}
Hashtable and ArrayList (and other collections) do not make a copy of key and value, and thus all values you are storing are the same probDes array you are allocating at the beginning (note that it is normal that the String[] appears in a cryptic form, you would have to make it pretty yourself, but you can still see that it is the very same cryptic thing all the time).
What is sure is that you should allocate a new probDes for each element inside the loop.
Based on your data you could work with an array as value in my opinion, there is no real use for the ArrayList
And the same applies to value, it has to be allocated separately upon encountering a new key:
private Hashtable<String, ArrayList<String[]>> readData() throws Exception {
try(BufferedReader br=new BufferedReader(new FileReader("MyGridWorld.txt"))) {
br.readLine();
Hashtable<String, ArrayList<String[]>> hashTableForWorld=new Hashtable<>();
//read file line by line
String line = null;
while ((line = br.readLine()) != null && !line.equals(";;")) {
//System.out.println("line ="+line);
String source;
String action;
//split by tab
String[] split = line.split("\\t");
source = split[0];
action = split[1];
String key = source+","+action;
String[] probDesRew = new String[3];
probDesRew[0] = split[2];
probDesRew[1] = split[3];
probDesRew[2] = split[4];
ArrayList<String[]> value = hashTableForWorld.get(key);
if(value == null){
value = new ArrayList<>();
hashTableForWorld.put(key, value);
}
value.add(probDesRew);
}
return hashTableForWorld;
}
}
Besides relocating the variables to their place of actual usage, the return value is also created locally, and the reader is wrapped into a try-with-resource construct which ensures that it is getting closed even if an exception occurs (see official tutorial here).
(Homework:) I want to use array instead of arraylist in this situation. I have the arraylist name Employee and i have to insert data of it into the tree. I load data line by line from file. But i want to use array for the Employee not arraylist. How can i do that ? There're any ways to use array instead of arraylist in this situation. The following code is my example code for arraylist Employee. I want to change List to Employee[] how can i write the following function in style of Array.
public static void main(String[] args) {
List<Employee> employees = read("employees.txt");
BST bst = new BST();
for(Employee e : employees){
bst.insert(e);
}
}
public static List<Employee> read(String file) {
try {
List<Employee> employees = new ArrayList<>();
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine()) != null ){
String[] arr = line.split("-");
Employee emp = new Employee();
emp.ccode = Integer.parseInt(arr[0]);
emp.cus_name = arr[1];
emp.phone = arr[2];
employees.add(emp);
}
return employees;
} catch (IOException ex) {
Logger.getLogger(TestMusic.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
This approach is not the best one, but might solve your problem. to be used for java versions < 8.
The approach is to parse the file to get no. of lines, to create the employee array, and parse again to get data of all the individual employees
public static void main(String[] args) {
int empSize = getNumberOfEmployees("employees.txt");
employees = new Employee[empSize];
employees = read("employees.txt");
BST bst = new BST();
for(Employee e : employees){
bst.insert(e);
}
}
public static int getNumberOfEmployees (String file) {
int totalEmp = 0;
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine()) != null ) {
totalEmp ++;
}
}catch (IOException e) {
e.printStackTrace();
}
return totalEmp;
}
public static Employee[] read(String file) {
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
int i=0;
while((line = reader.readLine()) != null ){
String[] arr = line.split("-");
Employee emp = new Employee();
emp.ccode = Integer.parseInt(arr[0]);
emp.cus_name = arr[1];
emp.phone = arr[2];
employees[i] = emp;
i++;
}
return employees;
} catch (IOException ex) {
Logger.getLogger(TestMusic.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
Without giving you any code (do it by yourself ;-)):
Parse the file twice:
get the number of lines, create an Array based on the number of lines
parse the file again, fill the Array
And some Research (keywords BufferedReader and Array) would help you too.
It is unclear from your requirements what you want to do in the following situations:
one line fails to parse;
cannot open the file for reading.
Here is a solution which (eww) will just ignore the unparseable entries and return an empty array if the file cannot be parsed:
public final class TestMusic
{
private static final Employee[] NO_EMPLOYEES = new Employee[0];
public static void main(final String... args)
{
final BST bst = new BST();
for (final Employee emp: getArray())
bst.insert(emp);
}
private static Employee toEmployee(final String input)
{
final String[] arr = input.split["-"];
final Employee emp = new Employee();
try {
emp.ccode = Integer.parseInt(arr[0]);
emp.cus_name = arr[1];
emp.phone = arr[2];
return emp;
} catch (NumberFormatException | IndexOutOfBoundsException e) {
return null;
}
}
private static Employee[] getArray()
{
final Path path = Paths.get("employees.txt");
try (
Stream<String> lines = Files.lines(path);
) {
return lines.map(TestMusic::toEmployee)
.filter(Objects::nonNull)
.toArray(Employee[]::new);
} catch (IOException ignored) {
return NO_EMPLOYEES;
}
}
}
Note how this solution does not use an intermediate list at all; instead, it makes use of the Java 8 Stream API.
What is left to do here is to handle errors... That is for you to decide :)
if you want to convert ArrayList to array use the following code:
Employee [] arrayOfEmpolyees = new Employee[employees.size()]
employees.toArray(arrayOfEmpolyees);
That is like doing a step backwards. Java collections (for example the List interface and the ArrayList implementation) have various advantages compared to "plain old" arrays.
The only real advantage of arrays is their reduced overhead - but that is only important when dealing with millions or billions of things to store in a container.
So the real answer is: don't do that. Just keep using List/ArrayList.
But in case you insist, you can of course use arrays - but then you have to add that part that makes ArrayList more convenient: you have to provide code that dynamically "grows" your array once you hit its size limit. That works like this:
you start with an initial array of size 100 for example
while populating that array, you keep track of the number of slots "in use"
when your code wants to add the 101st element, you "grow" the array
Growing works by:
creating a new array, that has like currentArray.length + 100 capacity
using System.arraycopy() to move all entries from the old to the new array
Guess the size of the array, for example by taking the size of the file and dividing by 20 (approximately the size of the line in the example you gave). Then read into the array, counting the lines. If the array is full before you have reached the end of the file, allocate a new array double the size, copy everything from the old array to the new array, replace the old array with the new array and continue the same way until done. You can look at the source of ArrayList to see an example of how it is done - basically this is what ArrayList does internally.
I am trying to read a file and pass it to a class called "Allabaque" that has a String and two List. When I have finished reading the first abaque I want to clear the two Lists so I can get the nexts values but if I clear the List, even if I do it after adding the new abaque, the function passes me the new abaque with the two empty Lists. Here is the code:
public void importFrom(String filename) {
try (
FileInputStream fis = new FileInputStream(filename);
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
String line;
String line2;
int c = 0;
List<String> Pression = new ArrayList<>();
List<String> Couple = new ArrayList<>();
List<String> P2 = new ArrayList<>();
List<String> C2 = new ArrayList<>();
String Cle = "null";
while ((line = reader.readLine()) != null) {
if (c == 2 && !"|".equals(line)) {
String[] arg = line.split("-");
boolean u = Pression.add(arg[0]);
boolean u2 = Couple.add(arg[1]);
}
if (c == 1) {
Cle = line;
c = 2;
//System.out.printf("%s",Cle);
}
if ("|".equals(line)) {
c = 1;
if (!"null".equals(Cle)) {
//P2 = Pression;
//C2 = Couple;
addAbaque(new Abaque(Cle, Pression, Couple));//addAbaque(new Abaque(Cle,P2,C2));
Couple.clear();
Pression.clear();
}
}
}
} catch (IOException ioe) {
System.out.printf("Erreur import");
}
}
The addAbaque method is the simple
public void addAbaque(Abaque abaque) {
mAbaques.add(abaque);``
}
Using the debug I think I have found that it's a problem with the memory but I reaaly dont know how to fix it.
I've tried also with two intermedieries List, I putted it like comments, but still nothing.
Clearing the Couple and Pression lists also clears the lists previously passed to the Abaque constructor, since you are passing List references to the constructor, not copies of the lists.
You can either pass new Lists to the constructor :
addAbaque(new Abaque(Cle,new ArrayList<String>(Pression),new ArrayList<String>(Couple)));
Or create new Lists instead of clearing the old ones, i.e. replace
Couple.clear();
Pression.clear();
with
Couple = new ArrayList<>();
Pression = new ArrayList<>();
The latter alternative is probably more efficient, since you don't have to copy the contents of the original Lists to new Lists, and you don't have to clear any Lists.
Here is the link which states the reading of data from csv to Hashmap.
Convert CSV values to a HashMap key value pairs in JAVA
However, I am trying to read a file of csv, in which there are multiple values for a given key.
Eg:
Key - Value
Fruit - Apple
Fruit -Strawberry
Fruit -Grapefruit
Vegetable -Potatoe
Vegetable -Celery
where , Fruit and Vegetable are the keys.
I am using an ArrayList<> to store the values.
The code I am writing is able to store the keys , but stores only the last corresponding value .
So, when I print the hashmap , what I get is : Fruit - [Grapefruit] Vegetable- [Celery]
How can I iterate through the loop, and store all the values?
Following is the code, which I have written :
public class CsvValueReader {
public static void main(String[] args) throws IOException {
Map<String, ArrayList<String>> mp=null;
try {
String csvFile = "test.csv";
//create BufferedReader to read csv file
BufferedReader br = new BufferedReader(new FileReader(csvFile));
String line = "";
StringTokenizer st = null;
mp= new HashMap<String, ArrayList<String>>();
int lineNumber = 0;
int tokenNumber = 0;
//read comma separated file line by line
while ((line = br.readLine()) != null) {
lineNumber++;
//use comma as token separator
st = new StringTokenizer(line, ",");
while (st.hasMoreTokens()) {
tokenNumber++;
String token_lhs=st.nextToken();
String token_rhs= st.nextToken();
ArrayList<String> arrVal = new ArrayList<String>();
arrVal.add(token_rhs);
mp.put(token_lhs,arrVal);
}
}
System.out.println("Final Hashmap is : "+mp);
} catch (Exception e) {
System.err.println("CSV file cannot be read : " + e);
}
}
}
Currently, you're putting a new ArrayList in your map for each value you find. This replaces the old list you had for that particular key. Instead, you should use the existing array list (if it is already there), and add your value to it.
You should therefore replace this:
ArrayList<String> arrVal = new ArrayList<String>();
arrVal.add(token_rhs);
mp.put(token_lhs,arrVal);
By this:
ArrayList<String> arrVal = mp.get(token_lhs);
if (arrVal == null) {
arrVal = new ArrayList<String>();
mp.put(token_lhs,arrVal);
}
arrVal.add(token_rhs);
you have:
while readline
while splitline
new ArrayList(); and list.add()
map.put(key, arraylist)
so everytime you executed the map.put(), a new arrayList would be put into the map, and the value of existing key would be overwritten with the new arraylist. You need first get the arrayList from the map, with certain key, and append the value to the arraylist. if key doesn't exist, create a new arrayList.
If you want to save that part of work, you could consider to use some MultiMap api, E.g guava ArrayListMultiMap
This is because you create a new arrVal list every time.
You should try this code
ArrayList<String> arrVal = mp.get(token_lhs);
if(arrVal == null) {
arrVal = new ArrayList<String>();
mp.put(token_lhs, arrVal);
}
arrVal.add(token_rhs);
It seems that you always initalize a new ArrayList inside your while (st.hasMoreTokens()) loop, so you will only have the last ArrayList used (containing only the last token of the csv line)
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.