in the following code, I have a method which is supposed to take data from a text file (lastname, firstname, classname) and tell whether the student was present or not (attendance), then populate a table with the value of "only" students present a certain number of times (basically present less than the times specified by input into a textfield). I tried using a hashmap, but am unsure as to where to put the "put" statement(s) in order to populate the hashmap correctly. I get repeats of information in the table and I do not want duplicates. My code is as follows: Any help would be greatly appreciated.
public void processFile() throws FileNotFoundException{
DefaultTableModel model = (DefaultTableModel) this.jTable_areasOfConcern.getModel();
File g = new File("pupilSortTemp.txt");
InputStream is;
Scanner scan = null;
HashMap<Integer, String> attendanceList = new HashMap<>();
try {
String firstName;
String lastName;
String className;
String studentKey;
String tab = "\t";
String attendance;
int attendanceCount = 0;
int totalDaysOrLessStudentsPresent;
totalDaysOrLessStudentsPresent = Integer.valueOf(this.jTextField_totalDays.getText());
is = new FileInputStream(g);
scan = new Scanner(is);
String[] array;
String line = scan.nextLine();
if (line.contains(tab)) {
array = line.split(tab);
}
else {
array = line.split("\n");
}
firstName = array[0];
lastName = array[1];
className = array[2];
attendance = array[4];
System.out.println("firstName=" + firstName);
System.out.println("lastName=" + lastName);
System.out.println("className=" + className);
System.out.println("attendance=" + attendance);
if (attendance.equals("Present")){
attendanceCount++;
studentKey = firstName + tab + lastName + tab + className;
attendanceList.put(attendanceCount, studentKey);
System.out.println("attendanceCountIfPresent=" + attendanceCount);
}
System.out.println("attendanceCountIfNotPresent=" + attendanceCount);
while (scan.hasNextLine()) {
line = scan.nextLine();
if (line.contains(tab)) {
array = line.split(tab);
}
else {
array = line.split("\n");
}
System.out.println("array0=" + array[0]);
System.out.println("array1=" + array[1]);
System.out.println("array2=" + array[2]);
System.out.println("array4=" + array[4]);
if (array[0].equals(firstName) && array[1].equals(lastName)){
if (array[4].equals("Present") && (attendanceCount < totalDaysOrLessStudentsPresent)){
attendanceCount++;
//studentKey = firstName + tab + lastName + tab + className;
//attendanceList.put(attendanceCount, studentKey);
System.out.println("attendanceCountIfPresent==" + attendanceCount);
model.addRow(new Object[]{array[2], array[1], array[0], attendanceCount, true});
}
}else {
if (array[4].equals("Present") && (attendanceCount < totalDaysOrLessStudentsPresent)){
attendanceCount = 1;
System.out.println("attendanceCountIfPresent++=" + attendanceCount);
firstName = array[0];
lastName = array[1];
className = array[2];
attendance = array[4];
model.addRow(new Object[]{array[2], array[1], array[0], attendanceCount, true});
studentKey = firstName + tab + lastName + tab + className;
attendanceList.put(attendanceCount, studentKey);
}
else {
attendanceCount = 0;
}
}
//attendanceList.put(attendanceCount, studentKey);
}//end while
for (Map.Entry<Integer, String> entry : attendanceList.entrySet()) {
studentKey = entry.getValue();
attendanceCount = entry.getKey();
array = studentKey.split(tab);
model.addRow(new Object[]{array[2], array[1], array[0], attendanceCount, true});
}
}catch (FileNotFoundException e){
}
finally{
if(scan != null){
scan.close();
}
}
}
I don't think that I'd use a HashMap as you're doing it, and if I did, the attendance count certainly would not be used as the key field for the map. All this will do is guarantee that only one student with that attendance count is entered into the collection. Create a Student class, give it the needed fields, including name, perhaps studentId, and yes, attendanceCount, and create a collection of that, perhaps an ArrayList<Student>. Then if you wanted to sort it, you could use a Comparator that sorted the attendanceCount values, or if you wanted to filter it, you could filter it using the same field's value.
Also, I'd have my Student class override equals and hashCode, and would use invariant fields for these methods, and most definitely not the attendance field. If the Student already exists in the ArrayList, by calling contains(student) on the List, then I'd increment the attendance of that student. Otherwise I'd add a new Student to the List.
If you have to use a HashMap, then you would reverse your key and value fields, i.e., have it as a HashMap<Student, Integer> where the value is the attendance count. Again for this to work Student would need to have its equals and hashCode methods overridden using an invariant field or fields within these methods, such as studentID.
Related
So I'm converting a CSV into an Array. The CSV has the first column which consists of titles the describe what is in that column. In my case: product ID | product name | product cost | quantity
I'm trying to go through the array, find the string item1 and then go to that item's quantity, which in the same line, but in a different column.
For example:
product ID | product name | product cost | quantity
-----001----- | -----item1----- | -----5.99----- | -----3-----
-----002----- | -----item2----- | -----2.99----- | -----5-----
So I want to go this array, find the string item1 in line index 1, then go to column index 3 to extract the quantity into a variable. Then I want to store into a variable to ultimately print out there are only 3 item1's left or something of the sort.
This is what I got so far:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class test2 {
public static List<List<String>> csvToArray() {
String fileName = "c:\\temp\\test.csv";
File file = new File(fileName);
// this gives you a 2-dimensional array of strings
List<List<String>> lines = new ArrayList<>();
Scanner inputStream;
try {
inputStream = new Scanner(file);
while (inputStream.hasNext()) {
String line = inputStream.next();
String[] values = line.split(",");
// this adds the currently parsed line to the 2-dimensional string array
lines.add(Arrays.asList(values));
}
inputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return lines;
}
public static void printArray(List<List<String>> lines){
int lineNo = 1;
for (List<String> line : lines) {
int columnNo = 1;
for (String value : line) {
System.out.println("Line " + lineNo + " Column " + columnNo + ": " + value);
columnNo++;
}
lineNo++;
}
}
public static void main(String[] args) {
csvToArray();
printArray(csvToArray());
}
}
As you can see, in the method printArray I'm just printing out the Array to get a reference of where I am, but once I try to add if's then Im getting lost.
Any help would be great :)
Determine the indexes of the clumns of interest and iterate through the lines, printing and feeding a variable for future use along the way.
Creating a class to represent a csv line seems to be over-engineering here but depends on the requirements, of course.
Code is not tested.
/*
Preprocessing:
Determine column indexes of product name and quantity.
Use the informstion available.
Simple case: column indices are known beforehand.
This code scans the csv header lines for given strings.
*/
final String s_HEADER_PRODUCT = "product name";
final String s_HEADER_QUANTITY = "quantity";
HashMap<String, int> quantities = new HashMap<String, int>();
int idxProduct = -1;
int idxQuantity = -1;
List<String> headers = lines[0];
int columnNo = 0;
for ( columnNo = 0; columnNo < headers.size(); columnNo++ ) {
if ((idxProduct < 0) && headers[columnNo].equals( s_HEADER_PRODUCT )) { idxProduct = columnNo; }
if ((idxQuantity < 0) && headers[columnNo].equals( s_HEADER_QUANTITY )) { idxQuantity = columnNo; }
if ((idxProduct >= 0) && (idxQuantity >= 0)) {
break;
}
}
/*
Print out.
After the loop, 'quantities' will hold a map of product names onto quantities.
Assumptions:
- Quantities are integer values.
- Product names are unique within the file.
*/
lineNo = 0;
for (List<String> line : lines) {
if (lineNo > 0) { // skip header line
System.out.println("Item '" + line.get(idxProduct) + "': " + line.get(idxQuantity) + " specimens left.");
quantities.put ( line.get(idxProduct), Integer.parseInt ( line.get(idxQuantity) );
}
lineNo++;
}
The best solution is to map each line to a "Product" object.
This news class will contains attributes like productID, productName, productCost & quantity.
Once each lines map to a product object, you just have to find the product with the productName you want, then you can access its other properties easily.
It would be better if you use List<String[]> instead of List<List<String>>.
But for your problem, you can do something like that:
for (int i = 0; i < lines.size(); i++)
System.out.println("There are only " + lines.get(i).get(3).replace("-", "") + " " + lines.get(i).get(1).replace("-", "") + "'s left");
I have this code...
Donor newDonor = new Donor(null,
donor.getName().split(" ")[0],
donor.getName().split(" ")[1],
address);
The problem is I am not allowed to change donor to have separate fields of first name and surname. So now the above code requires a surname. What if they don't enter it. Shall I do an if statement, if so how? Or is there a way to define a default value. So if they don't enter a surname, the default is nothing (""). Please advice.
String[] names = donor.getName().split(" ");
String first = names[0];
String last = names.length > 1? names[1] : "";
Donor newDonor = new Donor(null, first, last, address);
If for whatever reasons you want the check in params of constructor
Donor newDonor = new Donor(null,
donor.getName().split(" ")[0],
donor.getName().split(" ").length >1 ? donor.getName().split(" ")[1]: "",
address);
You can add a space at the end, and care about it (-1 in split function) in case there is only one word
String[] names = (fullName + " ").split("\\s+", -1);
Donor newDonor = new Donor(null, names[0], names[1], "address");
How about to create a sort of adapter class to do the dirt work. Something like this:
public class DonorAdapter {
private static final String DEFAULT_NAME = "xyz";
private static final String DELIMITER = " ";
private String name;
private String surnameName;
public DonorAdapter(Donor donor) {
String[] s = donor.getName().split(DELIMITER);
name = s.length - 1 >= 0 ? s[0] : DEFAULT_NAME;
surnameName = s.length - 1 >= 1 ? s[1] : DEFAULT_NAME;
}
public String getName() { return name; }
public String getSurname() { return surnameName; }
}
Then your code would be simpler and IMO more elegant.
DonorAdapter adapter = new DonorAdapter(donor);
Donor newDonor = new Donor(null, adapter.getName(), adapter.getSurname(), address);
I am making a while loop that asks for a name and an id and adds it to an ArrayList repeatedly until told to stop for my computer science class. How could I get the name of the new "TeamMember" to change every time? Also, would that even work and if not why and how could I get it to work?
This is my code (Main):
import java.util.ArrayList;
import java.util.Scanner;
public class TeamClassMain {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
ArrayList <TeamMember> list = new ArrayList();
String name;
String id;
String ArrayVar;
int number = 0;
int stop = 0;
while (stop == 0) {
System.out.println("Enter the next name:");
name = scan.nextLine();
name = name.toLowerCase();
if (name == "stop") {
stop = 1;
}
System.out.println("Enter the next ID:");
id = scan.nextLine();
ArrayVar = "member " + number;
TeamMember member1 = new TeamMember(name, id);
number++;
}
}
}
This isn't necessary, but it might be interesting to know what TeamMember is so this is my TeamMember class:
import java.lang.*;
public class TeamMember {
String fullName;
String idString;
TeamMember(String name, String id) {
name = name.toUpperCase();
char character;
String string;
int num;
for (int i = 0; i < name.length() - 1; i++) {
if (i == 0) {
character = name.charAt(0);
string = "" + character;
string = string.toUpperCase();
character = string.charAt(0);
i = character;
}
if (name.charAt(i) == ' ') {
character = name.charAt(i + 1);
string = "" + character;
string = string.toUpperCase();
character = string.charAt(i + 1);
name.substring(i + 1, character);
}
}
fullName = name;
idString.valueOf(id);
}
public String toString() {
return fullName;
}
int compareTo(TeamMember other) {
return idString.compareTo(other.idString);
}
}
Step 1 - Don't use a hammer to drive screws.
Specifically,
pay attention to the input data: you are asking the user to enter a map value between a name and an id.
It appears that the name is the key and the id is the value.
Store map "stuff" in a Map.
Step 2 - The TeamMember class provides just about 0 value. Just use the map between name and id.
In a less toy problem, TeamMember would do more that map between name and id.
In that case,
determine which is the appropriate key (id or name) and allocate (use new) a new TeamMember as the value each time you insert into the Map.
you need to add TeamMember to ArrayList
TeamMember member1 = new TeamMember(name, id);
list.add(member1);//add to list
you should break the while loop after stop that stop not gonna add in list
and use equal for comparing the string
if (name.equals("stop")) {
stop = 1;
break;
}
so first here is my code :
public class eol {
public static void main(String[] args) {
String x = "Charles.Baudelaire*05051988*France Sergei.Esenin*01011968*Russia Herman.Hesse*23051996*Germany";
String[] word= x.split("[.,*, ]");
for(int i=0;i<word.length;i++){
// System.out.print(word[i]+" ");
}
String name = word[0];
String lastname = word[1];
String dod =word[2];
String cob= word[3];
System.out.print("First person data : "+
"\n"+ name +" "+ "\n"+lastname+" "+"\n"+ dod+" "+"\n"+ cob);
I want to loop through string x, and take needed values, and use them to make 3 objects of class writer, is there any way i do this with for loop ?
Or would i have to "break" original string in 3 smaller arrays, then do for loop for every one of them.
I mean, i can use for loop to print out data on screen, by incrementing counter by certain value, how ever to add these data to fields is something I don't understand how to do.
Sure. You can do the following:
Validate.isTrue(word.length % 4 == 0, "Array size must be a multiple of 4");
List<Writer> writers = new ArrayList<>();
for (int i=0; i<word.length; i+=4) {
String name = word[i];
String lastname = word[i+1];
String dod =word[i+2];
String cob= word[i+3];
writers.add(new Writer(name, lastname, dod, cob));
}
i += 4 instead of i++ after each tern of loop, and use word[i], word[i+1], word[i+2] and word[i+3] in loop.
i.e.
String x = "Charles.Baudelaire*05051988*France Sergei.Esenin*01011968*Russia Herman.Hesse*23051996*Germany";
String[] word= x.split("[.,*, ]");
for(int i=0;i<word.length;i+=4){
String name = word[i];
String lastname = word[i+1];
String dod =word[i+2];
String cob= word[i+3];
// Use these variable.
}
I have LinkedHashMap<String,List<SelectItem>> results = got the results from DB see here
I need to assign the above results to the lists available in UI using for loop.
for (Map.Entry<String, List<SelectItem>> entry : results.entrySet()) {
String key = entry.getKey();
List<SelectItem> values = entry.getValue();
System.out.println("Key = " + key);
System.out.println("Values = " + values + "n");
}
Assigning part example :
if(key.equalsIgnoreCase("getProjectManager")) {
tempselectedProjMgrList = entry.getValue();
}
Based on the key I am adding the values to a diff list like the one i said in the given link above.
The above sys out does not print the acutal values inside the list instead it prints like the one given below ..
Key = getProjectManager
Values = [javax.faces.model.SelectItem#fadb0a,javax.faces.model.SelectItem#1245c45]n
Key = getResourceOwnerSE
Values = [javax.faces.model.SelectItem#25f52c, javax.faces.model.SelectItem#323fc] <br/>
How to get the actual values from the above list.
SelectItem did'nt override the toString() method herited from the Object class which is :
getClass().getName() + '#' + Integer.toHexString(hashCode())
That's why you get such an output.
So you'll have to loop through all the values and call getValue(). That will call the toString() method on the value object hold by the SelectItem.
System.out.println("Key = " + key);
System.out.println("Values = ");
for(SelectItem st : values){
System.out.print(st.getValue()+" ");
}
System.out.println();
EDIT:
If you want directly to get the appropriated list with the key associated, just do
tempselectedResOwnSeList = results.get("getProjectManager");
You can do the below:
First create a toString method for your SelectItem class with all the info you want to be printed . For example:
public class SelectItem {
private int a;
private String b;
#Override
public String toString() {
return "SelectItem [a=" + a + ", b=" + b + "]";
}
}
then do:
for (Map.Entry<String, List<SelectItem>> entry : results.entrySet()) {
String key = entry.getKey();
List<SelectItem> values = entry.getValue();
System.out.println("Key = " + key);
System.out.print("Values = ");}
for (SelectItem selectItem : values){
System.out.print(selectItem.toString() + "n");
}
}