Using array as key for hashmap java - java

i have a method that puts some value(obtained from an excel file) into a hashmap with an array as the key
public HashMap<List<String>, List<String[]>> sbsBusServiceDataGnr() throws
IOException
{
System.out.println(engine.txtY + "Processing HashMap "
+ "sbsBusServiceData..." + engine.txtN);
int counterPass = 0, counterFail = 0, stopCounter = 0;
String dataExtract, x = "";
String[] stopInfo = new String[3];
List<String[]> stopsData = new ArrayList<String[]>();
List<String> serviceNum = new Vector<String>();
HashMap<List<String>, List<String[]>> sbsBusServiceData =
new HashMap<List<String>, List<String[]>>();
String dataPath = this.dynamicPathFinder(
"Data\\SBS_Bus_Routes.csv");
BufferedReader sbsBusServiceDataPop = new BufferedReader(
new FileReader(dataPath));
sbsBusServiceDataPop.readLine();
//Skips first line
while ((dataExtract = sbsBusServiceDataPop.readLine()) != null) {
try {
String[] dataParts = dataExtract.split(",", 5);
if (!dataParts[4].equals("-")){
if (Double.parseDouble(dataParts[4]) == 0.0){
sbsBusServiceData.put(serviceNum, stopsData);
String serviceNum1 = "null", serviceNum2 = "null";
if(!serviceNum.isEmpty()){
serviceNum1 = serviceNum.get(0);
serviceNum2 = serviceNum.get(1);
}
System.out.println("Service Number " + serviceNum1
+ ":" + serviceNum2 + " with " + stopCounter
+ " stops added.");
stopCounter = 0;
//Finalizing previous service
serviceNum.Clear();
serviceNum.add(0, dataParts[0]);
serviceNum.add(1, dataParts[1]);
//Adding new service
}
}
stopInfo[0] = dataParts[2];
stopInfo[1] = dataParts[3];
stopInfo[2] = dataParts[4];
stopsData.add(stopInfo);
//Adding stop to service
stopCounter++;
counterPass++;
}
catch (Exception e) {
System.out.println(engine.txtR + "Unable to process "
+ dataExtract + " into HashMap sbsBusServiceData."
+ engine.txtN + e);
counterFail++;
}
}
sbsBusServiceDataPop.close();
System.out.println(engine.txtG + counterPass + " number of lines"
+ " processed into HashMap sbsBusServiceData.\n" + engine.txtR
+ counterFail + " number of lines failed to process into "
+ "HashMap sbsBusServiceData.");
return sbsBusServiceData;
}
//Generates sbsBusServiceDataGnr HashMap : 15376 Data Rows
//HashMap Contents: {ServiceNumber, Direction},
// <{RouteSequence, bsCode, Distance}>
this method work for putting the values into the hashmap but i cannot seem to get any value from the hashmap when i try to call it there is always a nullpointerexception
List<String> sbsTest = new Vector<String>();
sbsTest.add(0, "10");
sbsTest.add(1, "1");
System.out.println(sbsBusServiceData.get(sbsTest));
try{
List<String[]> sbsServiceResults = sbsBusServiceData.get(sbsTest);
System.out.println(sbsServiceResults.size());
String x = sbsServiceResults.get(1)[0];
System.out.println(x);
} catch(Exception e){
System.out.println(txtR + "No data returned" + txtN + e);
}
this is a sample of the file im reading the data from:
SBS
How can i get the hashmap to return me the value i want?

Arrays are not suitable as keys in HashMaps, since arrays don't override Object's equals and hashCode methods (which means two different array instances containing the exact same elements will be considered as different keys by HashMap).
The alternatives are to use a List<String> instead of String[] as the key of the HashMap, or to use a TreeMap<String[]> with a custom Comparator<String[]> passed to the constructor.

If you are having fixed array size then the example I'm posting might be useful.
Here I've created two Object one is Food and Next is Product.
Here Food object is use and added method to get string array.
public class Product {
private String productName;
private String productCode;
public Product(String productName, String productCode) {
this.productName = productName;
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
}
Food Model Class: Use as a Object instead of String[] and achieve String[] functionality.
public class Food implements Comparable<Food> {
private String type;
private String consumeApproach;
public Food(String type, String consumeApproach) {
this.type = type;
this.consumeApproach = consumeApproach;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getConsumeApproach() {
return consumeApproach;
}
public void setConsumeApproach(String consumeApproach) {
this.consumeApproach = consumeApproach;
}
public String[] FoodArray() {
return new String[] { this.type, this.consumeApproach };
}
//Implement compareTo method as you want.
#Override
public int compareTo(Food o) {
return o.getType().compareTo(this.type);
}
}
Using HashMap example
public class HashMapKeyAsArray {
public static void main(String[] args) {
HashMap<Food,List<Product>> map = dataSetLake();
map.entrySet().stream().forEach(m -> {
String[] food = m.getKey().FoodArray();
Arrays.asList(food).stream().forEach(f->{
System.out.print(f + " ");
});
System.out.println();
List<Product> list = m.getValue();
list.stream().forEach(e -> {
System.out.println("Name:" + e.getProductName() + " Produc Code:" + e.getProductCode());
});
System.out.println();
});
}
private static HashMap<Food,List<Product>> dataSetLake(){
HashMap<Food,List<Product>> data = new HashMap<>();
List<Product> fruitA = new ArrayList<>();
fruitA.add(new Product("Apple","123"));
fruitA.add(new Product("Banana","456"));
List<Product> vegetableA = new ArrayList<>();
vegetableA.add(new Product("Potato","999"));
vegetableA.add(new Product("Tomato","987"));
List<Product> fruitB = new ArrayList<>();
fruitB.add(new Product("Apple","123"));
fruitB.add(new Product("Banana","456"));
List<Product> vegetableB = new ArrayList<>();
vegetableB.add(new Product("Potato","999"));
vegetableB.add(new Product("Tomato","987"));
Food foodA = new Food("Fruits","Read To Eat");
Food foodB = new Food("Vegetables","Need To Cook");
Food foodC = new Food("VegetablesC","Need To Cook C");
data.put(foodA, fruitB);
data.put(foodB, vegetableB);
data.put(foodA, fruitA);
data.put(foodC, vegetableA);
return data;
}
Using TreeMap example
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.TreeMap;
public class TreeMapKeyAsArray {
public static void main(String[] args) {
TreeMap<Food, List<Product>> map = dataSetLake();
map.entrySet().stream().forEach(m -> {
String[] food = m.getKey().FoodArray();
Arrays.asList(food).stream().forEach(f->{
System.out.print(f + " ");
});
System.out.println();
List<Product> list = m.getValue();
list.stream().forEach(e -> {
System.out.println("Name:" + e.getProductName() + " Produc Code:" + e.getProductCode());
});
System.out.println();
});
}
private static TreeMap<Food, List<Product>> dataSetLake() {
TreeMap<Food, List<Product>> data = new TreeMap<>();
List<Product> fruitA = new ArrayList<>();
fruitA.add(new Product("Apple", "123"));
fruitA.add(new Product("Banana", "456"));
List<Product> vegetableA = new ArrayList<>();
vegetableA.add(new Product("Potato", "999"));
vegetableA.add(new Product("Tomato", "987"));
List<Product> fruitB = new ArrayList<>();
fruitB.add(new Product("Apple", "123"));
fruitB.add(new Product("Banana", "456"));
List<Product> vegetableB = new ArrayList<>();
vegetableB.add(new Product("Potato", "999"));
vegetableB.add(new Product("Tomato", "987"));
Food foodA = new Food("Fruits", "Read To Eat");
Food foodB = new Food("Vegetables", "Need To Cook");
data.put(foodA, fruitB);
data.put(foodB, vegetableB);
data.put(foodA, fruitA);
data.put(foodB, vegetableA);
return data;
}
}

Related

group and sum sales in String array java

I have a text file as below:
Pen 100
Ink 50
Pen 150
Paper 20
and I want to sum each of the goods
the output should look like:
Pen 250
Ink 50
Paper 20
Max Pen 250
Min Paper 20
I write just only some code below and I stuck:
public static void readData(){
File infile = new File("D:\\itemData.txt");
String itemName = new String();
String[] nameList = new String[100];
String[] saleList = new String[100];
int sale;
int count =0;
try {
Scanner data = new Scanner(infile);
while (data.hasNext()) {
itemName = data.next();
sale = data.nextInt();
nameList[count] = name;
saleList[count] = String.valueOf(sale);
count++;
for (int i = 0; i < nameList.length; i++) {
if (nameList[i] != null) {
System.out.println(nameList[i] + " " + saleList[i]);
}
}
data.close();
}
} catch (IOException e) {
}}
Try the code below.
There were 2 issues in the code I could see.
a) You did not declare the variable count
b) You were printing while reading the data, and that is not desirable.
public static void readData(){
File infile = new File("D:\\itemData.txt");
String itemName = new String();
String[] nameList = new String[100];
String[] saleList = new String[100];
int sale;
int count = 0;
try {
Scanner data = new Scanner(infile);
while (data.hasNext()) {
itemName = data.next();
sale = data.nextInt();
nameList[count] = name;
saleList[count] = String.valueOf(sale);
count++;
data.close();
}
} catch (SIOException e) {
}
for (int i = 0; i < nameList.length; i++) {
if (nameList[i] != null) {
System.out.println(nameList[i] + " " + saleList[i]);
}
}
}
Also consider implementing something like this to keep track of maxes and mins for you:
package com.example.demo;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.collections4.map.HashedMap;
public class Inventory {
private Map<String, AtomicInteger> totals = new HashedMap<>();
private Map<String, AtomicInteger> maxes = new HashedMap<>();
private Map<String, AtomicInteger> mins = new HashedMap<>();
public void add(String name, int number) {
getOrCreateFromMap(totals, name, 0).addAndGet(number);
getOrCreateFromMap(maxes, name, Integer.MIN_VALUE).getAndUpdate(present -> (present < number) ? number : present);
getOrCreateFromMap(mins, name, Integer.MAX_VALUE).getAndUpdate(present -> (number < present) ? number : present);
}
private AtomicInteger getOrCreateFromMap(Map<String, AtomicInteger> map, String name, int initialValue) {
return map.computeIfAbsent(name, x -> new AtomicInteger(initialValue));
}
public int getTotal(String name) {
return getFromMap(totals, name);
}
public int getMax(String name) {
return getFromMap(maxes, name);
}
public int getMin(String name) {
return getFromMap(mins, name);
}
private int getFromMap(Map<String, AtomicInteger> map, String key) {
return map.computeIfAbsent(key, x -> new AtomicInteger())
.get();
}
public static void main(String[] args) {
Inventory i = new Inventory();
i.add("paper", 50);
i.add("paper", 150);
System.out.println(i.getTotal("paper"));
System.out.println(i.getMax("paper"));
System.out.println(i.getMin("paper"));
}
}
Here is a working example, for the mentioned problem statement -
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.stream.Collectors;
public class ReadAndSumFileData {
public static void main(String... arguments) throws IOException {
String filename = "C:/temp/SalesData.txt";
readData(filename);
}
private static void readData(String filename) throws IOException {
Map<String, Integer> map = Files.lines(Paths.get(filename))
.map(s -> s.split("\\s+"))
.collect(Collectors.groupingBy(a -> a[0], Collectors.summingInt(a -> Integer.parseInt(a[1]))));
map.entrySet().stream().forEach(e-> System.out.println(e));
}
}

Why is my Java Program returning only the last String in an ArrayList

I want my Java Program to return a String response based on if/else conditions but it only responds to the last element in the ArrayList.
I have been working on this for two days without success.
I will appreciate a direction as to what am doing wrongly. Thank You
import java.io.IOException;
import java.util.logging.Logger;
public class ScanUtility implements IScanUtility {
Logger logger = Logger.getLogger("ScanUtility");
private String performHostScan(String nodeName) {
Process OSCmdProcess = null;
Integer exitValue = null;
String OScmd = null;
String exitMessage = null;
String OScmd = new String("/usr/bin/ssh ansible#" + nodeName + " " + "/tmp/openscapscan.bash rheldisa");
try {
OSCmdProcess = Runtime.getRuntime().exec(OScmd);
exitValue = OSCmdProcess.waitFor();
if (exitValue.equals(0)) {
exitMessage = ("Succeeded on" + " " + nodeName);
return exitMessage;
} else {
exitMessage = ("Failed on" + " " + nodeName);
return exitMessage;
}
} catch (IOException ioExcep) {
ioExcep.printStackTrace();
} catch (InterruptedException interExcep) {
interExcep.printStackTrace();
}
return exitMessage;
}
//This method takes an ArrayList of hosts from the servlet controller
// and passes the list to the ScanUtility Method above
//============================================================
public String generateHostName(List<String> addressList){
String statusMessage = null;
for(String nodeName: addressList){
statusMessage = new ScanUtility().performHostScan(nodeName);
}
return statusMessage;
}
}
The problem is that you are overwriting statusMessage on ever iteration of your loop. I believe what you want to do is put all the Strings into an ArrayList<String>.
public ArrayList<String> generateHostName(List<String> addressList){
ArrayList<String> statusMessage = new ArrayList<>();
for(String nodeName: addressList){
statusMessage.add(new ScanUtility().performHostScan(nodeName));
}
return statusMessage;
}
Apparently, you want to return a list of status messages (a status message from each server that you are scanning).
public List<String> getResponsesFromAddresses(List<String> addresses) {
final ScanUtility scanUtility = new ScanUtility();
return addresses.stream()
.map(scanUtility::performHostScan)
.collect(Collectors.toList());
}
The method name is misleading. I have changed it to getResponsesFromAddresses - that is what the method actually does.
Try this:
public List<String> generateHostName(List<String> addressList){
List<String> statusMessages = new ArrayList<>();
for(String nodeName: addressList){
statusMessages.add(new ScanUtility().performHostScan(nodeName));
}
return statusMessages;
}

How to remove duplicate in list based on two custom objects

I have ProductDetail class which contains two variables productName and productVersion. I need to replace duplicate items in the list according to the latest productVersion.
Example:
class ProductDetails {
string productName;
string productVersion;
}
new ProductDetails("ios", "9.1.0")
new ProductDetails("android", "6.0.1")
new ProductDetails("android", "5.1.1")
new ProductDetails("ios", "10.0.0")
Result:
android 6.0.1
ios 10.0.0
Thanks in advance.
This should work out for you:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
public class ProductDetails {
private String productName;
private String productVersion;
private List<ProductDetails> productData = null;
public ProductDetails(String productName,String productVersion){
this.productName = productName;
this.productVersion = productVersion;
if(productData == null) {
productData = new ArrayList<ProductDetails>();
adNewProduct(this);
}
}
private void adNewProduct(ProductDetails p){
String[] s1 = p.productVersion.split(Pattern.quote("."));
for (ProductDetails dpp: productData) {
if (dpp.productName.equals(p.productName)) {
int index = productData.indexOf(dpp);
String[] s2 = dpp.productVersion.split(Pattern.quote("."));
for(int i = 0; i < s1.length; i++) {
int v1 = Integer.valueOf(s1[i]);
int v2 = Integer.valueOf(s2[i]);
if (v1 > v2) {
productData.set(index,p);
return;
}
}
}
}
productData.add(p);
}
#Override // you can modify it to how you want
public String toString(){
String s = "";
for (ProductDetails p: productData){
s += "ProductName: " + p.productName + " ProductVersion: " + p.productVersion + "\n";
}
return s;
}
//the main method
public static void main(String[] args) {
ProductDetails k = new ProductDetails("ios", "9.1.1");
k.adNewProduct(new ProductDetails("android", "5.1.1"));
k.adNewProduct(new ProductDetails("android", "6.0.1"));
k.adNewProduct(new ProductDetails("ios", "10.0.0"));
System.out.println(k);
}
}
Output:
ProductName: ios ProductVersion: 10.0.0
ProductName: android ProductVersion: 6.0.1
You can put all those objects into a Map<String, ProductDetails> and keep the one with the latest version.
List<ProductDetails> details = Arrays.asList(
new ProductDetails("ios", "9.1.0"),
new ProductDetails("android", "6.0.1"),
new ProductDetails("android", "5.1.1"),
new ProductDetails("ios", "10.0.0"));
// get part of version string
Function<Integer, Function<ProductDetails, Integer>> version =
n -> (pd -> Integer.valueOf(pd.getProductVersion().split("\\.")[n]));
// chain to comparator
Comparator<ProductDetails> versionComp = Comparator.comparing(version.apply(0))
.thenComparing(version.apply(1)).thenComparing(version.apply(2));
Map<String, ProductDetails> latest = new HashMap<>();
for (ProductDetails pd : details) {
String name = pd.getProductName();
if (! latest.containsKey(name) || versionComp.compare(latest.get(name), pd) < 0) {
latest.put(name, pd);
}
}
Afterwards, latest is:
{android=Sandbox.ProductDetails(productName=android, productVersion=6.0.1),
ios=Sandbox.ProductDetails(productName=ios, productVersion=10.0.0)}
Or, you can use Collectors.groupingBy and then use the same Comparator:
details.stream()
.collect(Collectors.groupingBy(ProductDetails::getProductName))
.values().stream().map(list -> Collections.max(list, versionComp))
.forEach(System.out::println);

Java: How to retrieve data from a control statement?

I'm creating an employee time clock for a java class. This portion of my program is for reporting an individual's time, and reporting all employees time. My code works well for the individual, but I'm having trouble converting it to work for all employees. Should I try looping through the whole file and retrieving as it goes? The information being inside a control statement is causing me problems. Also, to only look at a two-week period, would using calendar and date -14 days be a good way to accomplish that?
Any feedback on how to proceed appreciated.
package PunchinPunchout;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
public class IDchecker {
private static BufferedReader br;
private static BufferedReader br1;
static int total;
static int total1;
public static void main(String args[]) throws IOException {
getsubject();
}
public static void getsubject() throws FileNotFoundException, IOException {
ArrayList<Integer> totalhours = new ArrayList<>();
br = new BufferedReader(new FileReader("timeclock1.txt"));
br1 = new BufferedReader(new FileReader("newemployee8.txt"));
String line = "";
String line1 = "";
Scanner sc = new Scanner(System.in);
System.out.print("Enter an employee ID number: ");
String idnumber = sc.next();//read the choice
sc.nextLine();// discard any other data entered on the line
while ((line1 = br1.readLine()) != null) {
if (line1.contains(idnumber)) {
System.out.println("Employee Name & ID ");
System.out.println(line1);
}
}
while ((line = br.readLine()) != null) {
if (line.contains(idnumber + " ") && line.contains("in")) {
System.out.println();
System.out.println(" Date Time ID Punched");
System.out.println(line);
String regexp = "[\\s:\\n]+"; // these are my delimiters
String[] tokens; // here i will save tokens
for (int i = 0; i < 1; i++) {
tokens = line.split(regexp);
total = Integer.parseInt(tokens[1]);
}
} else if (line.contains(idnumber + " ") && line.contains("out")) {
System.out.println(line);
String regexp = "[\\s:\\n]+";
String[] tokens;
for (int i = 0; i < 1; i++) {
tokens = line.split(regexp);
total1 = Integer.parseInt(tokens[1]);
System.out.print("Total hours for " + tokens[0] + " are: ");
}
int dailytotal = total1 - total;
System.out.println(dailytotal + " hours");
totalhours.add(dailytotal);
}
}
System.out.println();
int sum = totalhours.stream().mapToInt(Integer::intValue).sum();
System.out.println("The total hours for the last two weeks is " + sum + " hours.");
}
}
*Output from timeclock1.txt
05/05/2014 05:00:00 508 in
05/05/2014 09:00:00 508 out
05/05/2014 03:00:00 509 in
05/05/2014 09:00:00 509 out
05/05/2014 03:00:00 510 in
05/05/2014 08:00:00 510 out
05/05/2014 08:00:00 511 in
05/05/2014 10:00:00 511 out
*Output from newemployee8.txt
james bush 10
bobby bush 11
john hunt 12
mick jag 13
jacob sanchez 14
Okay, this a little of an over the top example, but it highlights the power of a OO language like Java...
There are a number of ways that this might be achieved, based on your requirements. I've made a few assumptions (like a in is followed by an out for the same employee), but the basic gist is demonstrated.
The intention is centralise some of the functionality into re-usable and manageable blocks, reducing the code duplication. Access to the data is simplified and because it's done in memory, is faster...
To start with, you will want to create object representations of the employee and time clock data, this will make it easier to manager...
Employee Example
public class Employee {
private final int id;
private final String name;
public Employee(String text) {
String[] parts = text.split(" ");
id = Integer.parseInt(parts[2]);
name = parts[0] + " " + parts[1];
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
TimeClockEntry example
public class TimeClockEntry {
private Date inTime;
private Date outTime;
private int employeeID;
public TimeClockEntry(String text) throws ParseException {
String parts[] = text.split(" ");
employeeID = Integer.parseInt(parts[2]);
setClockTimeFrom(text);
}
public void setClockTimeFrom(String text) throws ParseException {
String parts[] = text.split(" ");
if ("in".equalsIgnoreCase(parts[3])) {
inTime = CLOCK_DATE_TIME_FORMAT.parse(parts[0] + " " + parts[1]);
} else if ("out".equalsIgnoreCase(parts[3])) {
outTime = CLOCK_DATE_TIME_FORMAT.parse(parts[0] + " " + parts[1]);
}
}
public int getEmployeeID() {
return employeeID;
}
public Date getInTime() {
return inTime;
}
public Date getOutTime() {
return outTime;
}
}
Now, we need some kind of "manager" to manage the details of these two classes, these managers should provide access methods which allow use to retrieve information that they manage. These managers will also be responsible for loading the data from the files...
EmployeeManager example
public class EmployeeManager {
private Map<Integer, Employee> employees;
public EmployeeManager() throws IOException {
employees = new HashMap<>(25);
try (BufferedReader br = new BufferedReader(new FileReader(new File("NewEmployee8.txt")))) {
String text = null;
while ((text = br.readLine()) != null) {
Employee emp = new Employee(text);
employees.put(emp.getId(), emp);
}
}
}
public List<Employee> getEmployees() {
return Collections.unmodifiableList(new ArrayList<Employee>(employees.values()));
}
public Employee getEmployee(int id) {
return employees.get(id);
}
}
TimeClockManager example
public class TimeClockManager {
private Map<Integer, List<TimeClockEntry>> timeClockEntries;
public TimeClockManager() throws IOException, ParseException {
timeClockEntries = new HashMap<>(25);
try (BufferedReader br = new BufferedReader(new FileReader(new File("TimeClock1.txt")))) {
String text = null;
TimeClockEntry entry = null;
int line = 0;
while ((text = br.readLine()) != null) {
if (line % 2 == 0) {
entry = new TimeClockEntry(text);
} else {
entry.setClockTimeFrom(text);
List<TimeClockEntry> empEntries = timeClockEntries.get(entry.getEmployeeID());
if (empEntries == null) {
empEntries = new ArrayList<>(25);
timeClockEntries.put(entry.getEmployeeID(), empEntries);
}
empEntries.add(entry);
}
line++;
}
}
}
public List<TimeClockEntry> getByEmployee(Employee emp) {
List<TimeClockEntry> list = timeClockEntries.get(emp.getId());
list = list == null ? new ArrayList<>() : list;
return Collections.unmodifiableList(list);
}
}
Now, internally, these managers are managing the data through the use of Maps, to make it easier to find data, specifically, this is most keyed on the employee's id
Now, once we have these, we can ask for information from the as we please...
public Report() {
try {
EmployeeManager empManager = new EmployeeManager();
TimeClockManager timeClockManager = new TimeClockManager();
for (Employee emp : empManager.getEmployees()) {
System.out.println("[" + emp.getId() + "] " + emp.getName());
for (TimeClockEntry tce : timeClockManager.getByEmployee(emp)) {
System.out.println(" "
+ CLOCK_DATE_TIME_FORMAT.format(tce.getInTime())
+ " to "
+ CLOCK_DATE_TIME_FORMAT.format(tce.getOutTime()));
}
}
} catch (IOException | ParseException exp) {
exp.printStackTrace();
}
}
Another approach would be to incorporate both managers into a single class. The basic idea would be to load the employee and time clock data, the time clock data would become a property of the Employee and you could simply be able to access it directly.
This is a slightly more elegant solution, as you have all the data contained within a single construct, but might not meet your needs
Fully runnable example
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import oracle.jrockit.jfr.parser.ParseException;
public class Report {
public static void main(String[] args) {
new Report();
}
public Report() {
try {
EmployeeManager empManager = new EmployeeManager();
TimeClockManager timeClockManager = new TimeClockManager();
for (Employee emp : empManager.getEmployees()) {
System.out.println("[" + emp.getId() + "] " + emp.getName());
for (TimeClockEntry tce : timeClockManager.getByEmployee(emp)) {
System.out.println(" "
+ CLOCK_DATE_TIME_FORMAT.format(tce.getInTime())
+ " to "
+ CLOCK_DATE_TIME_FORMAT.format(tce.getOutTime()));
}
}
} catch (IOException | ParseException exp) {
exp.printStackTrace();
}
}
public class EmployeeManager {
private Map<Integer, Employee> employees;
public EmployeeManager() throws IOException {
employees = new HashMap<>(25);
try (BufferedReader br = new BufferedReader(new FileReader(new File("NewEmployee8.txt")))) {
String text = null;
while ((text = br.readLine()) != null) {
if (!text.trim().isEmpty()) {
Employee emp = new Employee(text);
employees.put(emp.getId(), emp);
}
}
}
}
public List<Employee> getEmployees() {
return Collections.unmodifiableList(new ArrayList<Employee>(employees.values()));
}
public Employee getEmployee(int id) {
return employees.get(id);
}
}
public class TimeClockManager {
private Map<Integer, List<TimeClockEntry>> timeClockEntries;
public TimeClockManager() throws IOException, ParseException {
timeClockEntries = new HashMap<>(25);
try (BufferedReader br = new BufferedReader(new FileReader(new File("TimeClock1.txt")))) {
String text = null;
TimeClockEntry entry = null;
int line = 0;
while ((text = br.readLine()) != null) {
if (!text.trim().isEmpty()) {
if (line % 2 == 0) {
entry = new TimeClockEntry(text);
} else {
entry.setClockTimeFrom(text);
List<TimeClockEntry> empEntries = timeClockEntries.get(entry.getEmployeeID());
if (empEntries == null) {
empEntries = new ArrayList<>(25);
timeClockEntries.put(entry.getEmployeeID(), empEntries);
}
empEntries.add(entry);
}
line++;
}
}
}
}
public List<TimeClockEntry> getByEmployee(Employee emp) {
List<TimeClockEntry> list = timeClockEntries.get(emp.getId());
list = list == null ? new ArrayList<>() : list;
return Collections.unmodifiableList(list);
}
}
public class Employee {
private final int id;
private final String name;
public Employee(String text) {
System.out.println("[" + text + "]");
for (char c : text.toCharArray()) {
System.out.print((int) c + ",");
}
System.out.println("");
String[] parts = text.split("\\s+");
id = Integer.parseInt(parts[2]);
name = parts[0] + " " + parts[1];
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
public static final SimpleDateFormat CLOCK_DATE_TIME_FORMAT = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
public static final SimpleDateFormat CLOCK_DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");
public class TimeClockEntry {
private Date inTime;
private Date outTime;
private int employeeID;
public TimeClockEntry(String text) throws ParseException {
System.out.println("[" + text + "]");
for (char c : text.toCharArray()) {
System.out.print((int) c + ",");
}
System.out.println("");
String parts[] = text.split("\\s+");
employeeID = Integer.parseInt(parts[2]);
setClockTimeFrom(text);
}
public void setClockTimeFrom(String text) throws ParseException {
String parts[] = text.split("\\s+");
if ("in".equalsIgnoreCase(parts[3])) {
inTime = CLOCK_DATE_TIME_FORMAT.parse(parts[0] + " " + parts[1]);
} else if ("out".equalsIgnoreCase(parts[3])) {
outTime = CLOCK_DATE_TIME_FORMAT.parse(parts[0] + " " + parts[1]);
}
}
public int getEmployeeID() {
return employeeID;
}
public Date getInTime() {
return inTime;
}
public Date getOutTime() {
return outTime;
}
}
}

collections for sorting employee details by id & firstname

I have written a code to sort name by id and firstname.
import java.io.*;
import java.util.*;
public class TestEmployeeSort {
/**
* #param args
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String option=null;
System.out.println("Enter on which order sorting should be done \n1.Id \n2.FirstName \n3.LastName");
List<Employee> coll = Name_Insert.getEmployees();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
option=br.readLine();
int a=Integer.parseInt(option);
switch(a)
{
case 1:
Collections.sort(coll);
printList(coll);
break;
case 2:
Collections.sort(coll,new EmpSortByFirstName());// sort method
printList(coll);
break;
case 3:
Collections.sort(coll,new SortByLastName());// sort method
printList(coll);
}
}
private static void printList(List<Employee> list) {
System.out.println("EmpId\tFirstName\tLastName\tDate Of Joining\tDate of Birth");
for (int i=0;i<list.size();i++) {
Employee e=list.get(i);
System.out.println(e.getEmpId() + "\t" + e.getFirstName() + "\t" + e.getLastname() +"\t" + e.getDate_Of_Joining()+"\t"+e.getDate_Of_Birth());
}
}
}
for sorting by id and first name i have this code in the Sort_this class
public class EmpSortByFirstName implements Comparator<Employee>{
public int compare(Employee o1, Employee o2) {
return o1.getFirstName().compareTo(o2.getFirstName()); }}
similarly for id.
Now i want to change my program like i have to get input from uset on which basis you want to sort. If the user gives id, I have to sort by id. If the user gives firstname then sort by first name. I want to use if statement. If user enters 1 it has to sort by id 2 it has to sort by first name
Create a map of user input tokens (string, integer, etc.) to Comparator<Employee>, and just use the appropriate one.
Did you mean you want to get rid of using switch? If so, you can try having a map of registered soter:
import java.io.*;
import java.util.*;
public class TestEmployeeSort {
private static class EmployeeSortingManager {
private final List list;
private final Map<Integer, Comparator> registeredSorter = new HashMap<Integer, Comparator>();
public EmployeeSortingManager(List list) {
this.list = list;
registerAvailableSorters();
}
private void registerAvailableSorters() {
registeredSorter.put(1, null);
registeredSorter.put(2, new EmpSortByFirstName());
registeredSorter.put(3, new SortByLastName());
}
public void sortBy(int i) {
Comparator comparator = registeredSorter.get(i);
if (registeredSorter.get(i) != null) {
Collections.sort(list, comparator);
} else {
Collections.sort(list);
}
}
}
/**
* #param args
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String option = null;
System.out.println("Enter on which order sorting should be done \n1.Id \n2.FirstName \n3.LastName");
List<Employee> coll = Name_Insert.getEmployees();
EmployeeSortingManager employeeSortingManager = new EmployeeSortingManager(coll);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
option = br.readLine();
int a = Integer.parseInt(option);
employeeSortingManager.sortBy(a);
printList(coll);
}
private static void printList(List<Employee> list) {
System.out.println("EmpId\tFirstName\tLastName\tDate Of Joining\tDate of Birth");
for (int i = 0; i < list.size(); i++) {
Employee e = list.get(i);
System.out.println(e.getEmpId() + "\t" + e.getFirstName() + "\t" + e.getLastname() + "\t" + e.getDate_Of_Joining() + "\t" + e.getDate_Of_Birth());
}
}
}
Another attemp to remove implementation of Every single comparator through the use of reflection. This is mmore complicated and may introduced more error if you are working with values which are not Comparable, e.g. String, Integer, Double. You will have to be careful.
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
public class TestEmployeeSort {
private static class EmployeeSortingManager {
private final List list;
private final Map<Integer, Method> registeredSorter = new HashMap();
private BasicComparator comparator = new BasicComparator();
public EmployeeSortingManager(List list) {
this.list = list;
registerAvailableSorters();
}
private void registerAvailableSorters() {
registeredSorter.put(1, null);
registeredSorter.put(2, getEmployeeGetMethod("firstName"));
registeredSorter.put(3, getEmployeeGetMethod("lastName"));
}
private Method getEmployeeGetMethod(String fieldName) {
Method method = null;
try {
// create java style get method name from field name, e.g. getFieldName from fieldName
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
method = Employee.class.getMethod(getMethodName);
} catch (NoSuchMethodException ex) {
} catch (SecurityException ex) {
}
// null is return if you give invalid field name
return method;
}
public void sortBy(int i) {
Method get = registeredSorter.get(i);
if (get != null) {
comparator.setGetMethod(get);
Collections.sort(list, comparator);
} else {
Collections.sort(list);
}
}
}
private static class BasicComparator implements Comparator<Employee> {
private Method aGetMethod = null;
public void setGetMethod(Method aGetMethod) {
this.aGetMethod = aGetMethod;
}
#Override
public int compare(Employee o1, Employee o2) {
try {
Object value1 = aGetMethod.invoke(o1);
Object value2 = aGetMethod.invoke(o2);
if (value1 instanceof Comparable && value2 instanceof Comparable) {
// this should work with String, Integer, Double, etc. They all implement Comparable interface.
return ((Comparable) value1).compareTo((Comparable) value2);
} else {
// you will need to add your own comparision for other type of variable;
// obviously it is not possible to have a single comparison
// if your get method return something else.
}
} catch (IllegalAccessException ex) {
} catch (IllegalArgumentException ex) {
} catch (InvocationTargetException ex) {
}
// if cannot compare then they are equal.
return 0;
}
}
/**
* #param args
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String option = null;
System.out.println("Enter on which order sorting should be done \n1.Id \n2.FirstName \n3.LastName");
List<Employee> coll = Name_Insert.getEmployees();
EmployeeSortingManager employeeSortingManager = new EmployeeSortingManager(coll);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
option = br.readLine();
int a = Integer.parseInt(option);
employeeSortingManager.sortBy(a);
printList(coll);
}
private static void printList(List<Employee> list) {
System.out.println("EmpId\tFirstName\tLastName\tDate Of Joining\tDate of Birth");
for (int i = 0; i < list.size(); i++) {
Employee e = list.get(i);
System.out.println(e.getEmpId() + "\t" + e.getFirstName() + "\t" + e.getLastname() + "\t" + e.getDate_Of_Joining() + "\t" + e.getDate_Of_Birth());
}
}
}

Categories