Adding element to List from csv file like Arraylist.add - java

Here is my code:
public static Map<String, List<Customer>> readCustomerData() throws IOException {
Map<String, List<Customer>> customers =
Files.lines(Paths.get("customer.csv"))
.map(line -> line.split("\\s*,\\s*"))
.map(field -> new Customer(
Integer.parseInt(field[0]), field[1],
Integer.parseInt(field[2]), field[3]))
.collect(Collectors
.groupingBy(Customer::getName));
System.out.println (customers);
return customers;
}
I notice that this code read my data in the csv file into one element like this:
(Ali = ["1 Ali 1201345673 Normal"] , Siti = ["2 Siti 1307891435 Normal"])
But in my thinking , I would like to read the data like the array list such as for Ali: 1 is an element , Ali is an element , 1201345673 is an element and Normal is another element in the list in the Map customer. How can I modify my code to do such a thing?
This is my Customer class just in case:
public class Customer {
private int customerNo;
private String name;
private int phoneNo;
private String status;
public Customer () {}
public Customer (int customerNo, String name, int phoneNo, String status){
this.customerNo = customerNo;
this.name = name;
this.phoneNo = phoneNo;
this.status = status;
}
public String getName(){
return name;
}
public String toString(){
return customerNo + " " + name + " " + phoneNo + " " + status;
}
Here is my csv file:
1,Ali,1201345673,Normal
2,Siti,1307891435,Normal
Thank you for your attention.

Assuming that the customer names are unique, there's no need to return a Map<String, List<Customer>>, since each List will contain a single Customer.
You can change your code to:
Map<String, Customer> customers =
Files.lines(Paths.get("customer.csv"))
.map(line -> line.split("\\s*,\\s*"))
.map(field -> new Customer(
Integer.parseInt(field[0]), field[1],
Integer.parseInt(field[2]), field[3]))
.collect(Collectors.toMap(Customer::getName, Function.identity()));
And if the names are not unique, you can index the customers by the customer IDs.
As for I would like to read the data like the array list such as for Ali: 1 is an element , Ali is an element , 1201345673 is an element and Normal is another element in the list in the Map customer - this doesn't make sense to me. You already create a Customer object from each line of your input, which is much more useful and type safe compared to a List of properties.

Related

Searching data from arraylist

I am a newbie of c++.
Now I am doing a project need to read a customer list from a csv file and then search if there is a username like "Ali" and printout all the data about Ali.
How can I search "Ali" and printout all the data about Ali like CustomerNo , Name , PhoneNo and Status?
And if there is multiple data with "Ali" , how can I printout all of them either?
Here is my code:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Iterator;
public class LoadCustomer {
public static void main(String[] args) throws IOException{
System.out.println ("Load customer from file");
ArrayList<Customer> customers = readCustomerFromFile();
System.out.println (customers);
System.out.println ();
private static ArrayList<Customer> readCustomerFromFile() throws IOException{
ArrayList<Customer> customers = new ArrayList<>();
List<String> lines = Files.readAllLines(Paths.get("customer.csv"));
for (int i = 1 ; i < lines.size() ; i++){
String[] items = lines.get(i).split(",");
int customerNo = Integer.parseInt(items[0]);
int phoneNo = Integer.parseInt(items[2]);
customers.add (new Customer(customerNo,items[1],phoneNo,items[3]));
}
return customers;
}
}
Here is my Customer class:(added getName getter)
public class Customer {
private int customerNo;
private String name;
private int phoneNo;
private String status;
public Customer () {}
public Customer (int customerNo, String name, int phoneNo, String status){
this.customerNo = customerNo;
this.name = name;
this.phoneNo = phoneNo;
this.status = status;
}
public String getName(){
return name;
}
public String toString(){
return customerNo + " " + name + " " + phoneNo + " " + status;
}
public String toCSVString(){
return customerNo + "," + name + "," + phoneNo + "," + status;
}
}
And here is my data:
CustomerNo Name PhoneNo Status
1 Ali 12345 Normal
2 Siti 23456 Normal
3 Rone 78910 Normal
4 Jean 56789 Normal
5 Roby 28573 Normal
6 Ali 78532 Normal
Thank you very much for your attention.
Edited :
Here is my code for this program:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
public class FindCustomer {
public static void main(String[] args) throws IOException{
System.out.println ("Load customer from file");
java.util.Map<String, List<Customer>> customers =
Files.lines(Paths.get("customer.csv"))
.map(line -> line.split(","))
.map(field -> new Customer(
Integer.parseInt(field[0]), field[1],
Integer.parseInt(field[2]), field[3]))
.collect(Collectors
.groupingBy(Customer::getName));
System.out.println (customers);
}
}
Bit of a broad question.
If you expect to do this a lot, and on a boatload of data, do what everybody else does when they are faced with a lot of relational data that they need to run queries on. Use a database, like postgres or h2. To interact with those from java, use JDBI or JOOQ.
If this is just a small simple text file and/or you're trying to learn some java, well, you still have two options here: You can loop through the data, or, you can build a mapping.
The loop option is simple:
for (Customer c : customers) if (c.getName().equals("Ali")) {
// do what you want here. 'c' holds the customer object of Ali.
}
But this does, of course, require a full run through all the entries every time. Another option is to build a mapping:
var map = new HashMap<String, Customer>();
for (Customer c : customers) map.put(c.getName(), c);
// map now maps a customer name to the customer object.
Customer ali = map.get("Ali");
maps have the advantage that they are near instant lookup. Even if the map contains a million entries, map.get(x) is (near) instant. A decent solution if you have lots of data + the need to do lots of lookups. But, you have to build a complete map for everything you care to query on. So, if you want to do lookups on name, and then later something like 'get all customers with a 6 digit phone number whose status is Normal', then, get a database.
As was suggested a map would be useful. You can create one on the fly as you read in the file.
Splits the line
creates a customer.
and groups it by name in a map.
Now the map will hold for each name, all customers that have that name.
Map<String, List<Customer>> customers =
Files.lines(Paths.get("customer.csv"))
.map(line -> line.split("\\s*,\\s*"))
.map(field -> new Customer(
Integer.parseInt(field[0]), field[1],
Integer.parseInt(field[2]), field[3]))
.collect(Collectors
.groupingBy(Customer::getName));
To get the List of customers for the name Ali do the following.
List<Customer> ali = customers.get("Ali");
Now it's up to you to format or otherwise use the list as required. You will still need to handle exceptions via try/catch.

How to use BeanMapHandler with field to column mapping with key as ID in a nested SELECT query?

I have a nested SQL query to fetch employee details using their ID.
Right now I am using BeanListHandler to fetch data as a List<Details> but want to store it as a Map<String, Details> where the ID I originally pass needs to be the key for easy retrieval instead of searching the List with streams every time.
I have tried to convert to Maps but I am not sure of how to map the ID as String nor how to get the original ID passed to the inner Query as a column in the final result.
MainTest.java:
String candidateId = "('1111', '2222', '3333', '4444')";
String detailsQuery =
"select PARTNER, BIRTHDT, XSEXM, XSEXF from \"schema\".\"platform.view/table2\" where partner IN \r\n"
+ "(select SID from \"schema\".\"platform.view/table1\" where TYPE='BB' and CLASS='yy' and ID IN \r\n"
+ "(select SID from \"schema\".\"platform.view/table1\" where TYPE='AA' and CLASS='zz' and ID IN"
+ candidateId + "\r\n" + "))";
Map<String, Details> detailsView = queryRunner.query(conn, detailsQuery, new DetailsViewHandler());
Details.java:
public class Details {
private String candidateId;
private String birthDate;
private String maleSex;
private String femaleSex;
// getter and setter
}
DetailsViewHandler.java:
public class DetailsViewHandler extends BeanMapHandler<String, Details> {
public DetailsViewHandler() {
super(Details.class, new BasicRowProcessor(new BeanProcessor(getColumnsToFieldsMap())));
}
public static Map<String, String> getColumnsToFieldsMap() {
Map<String, String> columnsToFieldsMap = new HashMap<>();
columnsToFieldsMap.put("PARTNER", "candidateId");
columnsToFieldsMap.put("BIRTHDT", "birthDate");
columnsToFieldsMap.put("XSEXM", "maleSex");
columnsToFieldsMap.put("XSEXF", "femaleSex");
return columnsToFieldsMap;
}
}
Is there a way to get the ID (candidateId) in the result and what am I missing in terms of creating the key-value pairing ?
From the doc https://commons.apache.org/proper/commons-dbutils/apidocs/org/apache/commons/dbutils/handlers/BeanMapHandler.html
of constructor which you are using
public BeanMapHandler(Class<V> type,
RowProcessor convert)
// Creates a new instance of BeanMapHandler. The value of the first column of each row will be a key in the Map.
Above should work.
You can also try overriding createKey like so
protected K createKey(ResultSet rs)
throws SQLException {
return rs.getString("PARTNER"); // or getInt whatever suits
}

Implementing 2 Java Classes

I'm learning java and trying to implement two java classes.
Student: firstName, lastName, departmentIn, yearGraduation, an array of UAClass this student is taking, an array of integers corresponding to the grades received for these classes
UAClass: teacherFirstName, teacherLastName, semesterOffered, numCredits
In the Student class, implement a method that calculates GPA. In the Student’s main() method, initiate one Student object and print out her GPA.
In my student.java class I have:
import java.util.*;
public class Student {
private String firstName;
private String lastName;
private String departmentIn;
private String yearGraduation;
private float [] grade;
private int counter = 0;
private String Student;
public Student(String my_firstName, String my_lastName, String my_deptIn, String my_yearGrad) {
firstName = my_firstName;
lastName = my_lastName;
departmentIn = my_deptIn;
yearGraduation = my_yearGrad;
grade = new float[5];
}
public String toString(){
String value;
value = "First Name: " + firstName + "\n";
value += "Last Name : " + lastName + "\n";
value += "Department: " + departmentIn + "\n";
value += "Grad. Year: " + yearGraduation + "\n";
return value;
}
public static void main(String[] args) {
Student my1 = new Student("Bob", "Hope", "MBA", "2018");
Student my2 = new Student("John", "Smith", "MBA", "2020");
Student my3 = new Student("Jane", "Doe", "MBA", "2021");
UAClass cy1 = new UAClass[4];
String[] secondArray = cy1.getarrayClass();
System.out.println(my1);
System.out.println(my2);
System.out.println(my3);
System.out.println(Arrays.toString(cy1));
}
}
And in my UAClass.java class I have:
import java.util.*;
public class UAClass {
private String teacherFirstName;
private String teacherLastName;
private String semesterOffered;
private String numCredits;
private String[] arrayClass = {"MBA 501","MBA 505","MBA 513","MBA 545"};
public UAClass(String teacherF, String teacherL, String semesterO, String numC) {
teacherFirstName = teacherF;
teacherLastName = teacherL;
semesterOffered = semesterO;
numCredits = numC;
}
public String[] getarrayClass(){
return arrayClass.clone();
}
}
What I am trying to do is to create an Array in 'UAClass' and having it printed into 'Student' but I can't seem to get it working.
I've modified the code as Amit suggested. When I run it, I get this error.
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: Array.getarrayClass at Homework2.Student.main(Student.java:66)
It seems to be having an issue with String[] secondArray = cy1.getarrayClass();
I took out the line String[] secondArray = cy1.getarrayClass() and it seems to run fine but now all I get is [null, null, null, null]
First of all, your UAClass has one constructor that takes String teacherF, String teacherL, String semesterO, String numC as parameters.
So you need to call this constructor like this:
UAClass cy1 = new UAClass("Teacher F", "Teacher L", "Semester", "NumC");
Secondly, you use an String[] type. This is a low-level array type. You can do this in Java, but normally people rather use a List type, and then not the raw type, but better like List<String>. List is actually an interface, but you can reference it as the Arrays class returns an implementation of the List class.
You should then use:
private List<String> arrayClass = Arrays.asList("MBA 501","MBA 505","MBA 513","MBA 545");
And you return a clone of the array. I presume you do this because you don't want the array to be changed. I would just return a concatenated String with values. Here is a nice example with a stream.
public String getClasses() {
return arrayClass.stream().collect(Collectors.joining(","));
}
Now in the Student class you can just print the list of classes like this:
System.out.println(cy1.getClasses());
When you change your code like that it will work but I couldn't understand what you are trying to do in your code.
UAClass cy1 = new UAClass("Bob", "", "", "");
String[] secondArray = cy1.getarrayClass();
System.out.println(my1);
System.out.println(my2);
System.out.println(my3);
System.out.println(cy1.getarrayClass());

Java Convert List<String> to List<Object>

I've two classess CsvRead and MyOwnClass.
In CsvRead I've a method public static List getDataFromCsv(); It returns list of all data. And this data I want to take in another method in class MyOwnClass and return there as list of objects of My OwnClass
It looks like this:
List<String> dataFromCsv = new ArrayList<String>();
And in another class, I want to convert it to List<Object> of my class.
private static List<String> getDataFromCsvClass = new ArrayList<String>();
getDataFromCsvClass = CsvReader.getAllCsvData(filename);
String name = dataFromCsv[0];
String surname = dataFromCsv[1];
String birth = dataFromCsv[2];
I want to return new MyOwnClass(name, surname, birth);
MY ERROR: array required but List found: String name = allData[0]; etc
You can create a method to convert a String to MyOwnClass and use stream to map the elements, e.g.:
public static MyOwnClass convertToObject(String element){
String[] tokens = element.split(",");
return new MyOwnClass(tokens[0], tokens[1], tokens[2]);
}
//code to convert
List<String> dataFromCsv = new ArrayList<String>();
List<MyOwnClass> list = dataFromCsv.stream()
.map(e -> convertToObject(e))
.collect(Collectors.toList());
However, this may not work if let's say name or surname contains comma. In which case, I would recommend having a look at OpenCSV library and this example of how to read csv into objects.
Supposing that the list contains the name, surname and birth in every group of 3 strings (i.e., the elements on index 0, 3, 6, 9 etc. contain the name), you might try the following:
public List<MyOwnClass> convertCsvData(List<String> csv_data)
{
// Initialize result
List<MyOwnClass> result;
result = new ArrayList<MyOwnClass>();
// Parse data
int counter;
String name;
String surname;
String birth;
for (counter = 0; counter < csv_data.size(); counter += 3)
{
name = csv_data.get(counter);
surname = csv_data.get(counter + 1);
birth = csv_data.get(counter + 2);
result.add(new MyOwnClass(name, surname, birth));
}
// Done
return (result);
} // convertCsvData
Somthing like this :
private static MyOwnClass toMyOwnClass(String str){
String[] object= str.split(",");
return new MyOwnClass(object[0], object[1], object[2]);
}
List<String> dataFromCsv = new ArrayList<String>();
List<MyOwnClass> list = new ArrayList<>();
for(String string : dataFromCsv ){
if(StringUtils.isNoneEmpty(string)){
list.add(toMyOwnClass(string));
}
}
And then you return your list

Java HashMap, One key multiple Values, One map

As the question reads.... and I do NOT want to use multiple maps, just one map.
My goal is to get a list of the names I enter in the input.
I have tried like a hundred different for-loops, but I always tend to end up with a list of the whole map and/or that the duplicate key is overridden.
import java.util.*;
public class Another {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String name;
HashMap<String, ToA>wordkey = new HashMap<String, ToA>();
ToA a = new ToA("Doolin", "Bill", "18580824-1464");
ToA b = new ToA("Dalton", "Bob", "18701005-2232");
ToA c = new ToA("James", "Jesse", "18470905-2401");
ToA d = new ToA("Dalton", "Emmet", "18710713-0818");
wordkey.put("Doolin", a);
wordkey.put("Dalton", b);
wordkey.put("James", c);
wordkey.put("Dalton", d);
System.out.println("Efternamn:");
name = scan.next();
}
}
public class ToA{
private String fname, lname, dob;
public ToA(String fname, String lname, String dob){
this.fname = fname;
this.lname = lname;
this.dob = dob;
}
public String getFname(){
return fname;
}
public String getLname(){
return lname;
}
public String getDob(){
return dob;
}
public String toString(){
return "\nFirstname: " + fname + "\nSurname: " + lname + "\nDateOfBirth: " + dob;
}
}
For inputting Dalton, I would like the output
Firstname: Bill
Surname: Dalton
DateOfBirth: 18701005-2232
Firstname: Emmet
Surname: Dalton
DateOfBirth: 18710713-0818
I'm really stuck with this so any help is highly appreciated, Thanks
To post my comment as an answer: use a Map<String, List<ToA>> like this:
Map<String, List<ToA>> wordkey = new HashMap<>();
ToA a = new ToA("Doolin", "Bill", "18580824-1464");
ToA b = new ToA("Dalton", "Bob", "18701005-2232");
ToA c = new ToA("James", "Jesse", "18470905-2401");
ToA d = new ToA("Dalton", "Emmet", "18710713-0818");
wordkey.put("Doolin", Arrays.asList(a));
wordkey.put("James", Arrays.asList(c));
wordkey.put("Dalton", Arrays.asList(b, d));
To print the names based on the input, you can do something like this:
System.out.println("Efternamn:");
name = scan.next();
List<ToA> toas = wordkey.get(name);
if (toas != null) {
System.out.println("ToAs");
for (ToA toa : toas) {
System.out.println("ToA: " + toa);
}
}
else {
System.out.println("No ToAs found for input: " + name);
}
There are several possibilities for what you are trying to achieve. A simple one would be to use Guavas Multimap or to use Apaches MultiMap.
Another possibility is to "wrap" the Map in a class and keep a List<ToA> as Value of the Map. You'd override the put, remove and get methods to what you need

Categories

Resources