I need to perform Joins on 2 tables (that I have read from 2 CSV files) without use of database. I have no idea on collections (List, ArrayList). If anyone can give a detail piece of sample code on any one type of join that would be helpful.
For example I have 2 lists :
a=[2,3,4]
b=[3,4,5]
If it is an inner join
output: [3,4]
Tried so far:
for i in a:
for j in i:
if (i==j):
print(i)
Assuming that you have the following CSV files:
id,name,description
1,Foo,FooBar
2,Bar,BarFo
3,Hey,Ho
and the second one:
id,year
2,1990
1,1923
Then you could have the following structures (I'm skipping the constructors and methods for now):
public class Item {
public String name;
public String description;
}
and the second:
public class Date {
public final int year;
}
Then you could have a third one:
public class Joined {
public final Item item;
public final Date date;
}
And then you could have a Map<Integer,Joined>, and you can read the first CSV and create the Joined objects with only the Item part filled out, then read the second CSV and you could fill up the Date part of the Joined object.
In this joining part, you can decide which joining type you want to implement.
If you have a different key, then you have to change the key of the Map, or you may need to create a new class if you have a complex key.
Related
This is more of a "Design" or "Conception" sort of question.
So I have a simple problem; I want to print some workers info in an Excel sheet.
But I want to do it in a way that is easy to change in the future, let me explain : for now, people just want to see last name, first name and address in that excel table. But, what if all of a sudden they want more ? Or less ? How to add or remove a column (that actually refers to a field in the Worker class) hassle free ?
In a simple picutre, I want a simple system to go from this (these would be excel sheets) :
| first name | age | job |
-----------------------------------
| joe | 26 | developer |
| mary | 25 | tester |
to this :
| first name | last name | status | adress |
---------------------------------------------------------
| joe | johnson | employee | 8 sun street |
| mary | hoover | bos | 6 moon street |
So my class is Worker, I thought about making a class that is called WorkerTabular that would have a List of java.lang.reflect.Field references in it, and then I can check, but I don't want to break the encapsulation, that would kind of defeat the purpose of making an "easily variable system", if all of a sudden we tie to the implementation and oversee getters. So instead I thought of storing the references to the getter methods in this List of columns. But how would I call that function reference I stored on an instance of Worker?
Something like (using the builder pattern) WorkerTabular().addColumn(Worker::getName).addColumn(Worker::getHiringDate) and then, in a third class like ExcelMaker do something like worker.call(Worker::getName) to get the name.
I want to keep things as segregated as possible to make a truly reusable thing, by leaving the Worker Entity untouched, encapsulating the tabular data we want in the WorkerTabular, and the actual work of making the Excel stuffs in the ExcelMaker class.
Am I missing a well known pattern to do all this ? After all, making a kind of "variable excel sheet" must not be a new problem.
In other languages like Javascript, I can kind of see how that would be done, WorkerTabular would be made with that builder pattern just that it's a List of Strings, and then in ExcelMaker we would just do worker[listElement] while iterating on the list of attributes we chose to be in the Excel sheet. But in Java, I can't really see a clean and "Javaic" way to do it.
I'm sorry if I'm asking a stupid question.
EDIT 1 :
Thanks to Justin Albano for his nice answer :).
You really nailed it I think with the usage of the interface, even the fact that not every field is a String can be handled in the Implementation of TableEntry, by doing the conversion there (Dates to Strings, Ints to Strings, etc). There is a bit of coupling between TableEntry and Worker, but it's kept there and TableBuilder can really just concentrate of it's job of iterating over the List of Strings and build the Excel file.
I'm having a bit of trouble figuring out how to add a "columns titles" line to the TableBuilder, but I guess I'll just do it like this :
class TableBuilder {
List<String> columnTitles;
String tableTitle;
bytes[] build(List<TableEntry> lte) {
// make first row, make title & iterate over entries
// then do miscellaneous things like set the correct merged region for title, etc
}
}
And initialize those fields with a static factory or builder.
Actually this problem arose :
there are two types of Workers, and they have two fields : email and work_email.
A type of worker has both, and the other type has only work_email. So with my implementation I'm screwed ! I would have to put BOTH fields in the Excel table,
and one would be empty for the other type of worker, and people would complain !
Or I would need to split the function generating the Excel file in two thus duplicating a lot of code, or handle this little weird case in the function making it really ugly.
With the implementation with Entry interface to represent data, I can get around this easy ! I get the feeling that it's a bit "overengineered" and certainly my colleagues won't like stumbling through this implementation I think (the codebase is more of a "straight to the point and ugly don't matter" kind of thing), but it's also very clean I feel.
Moreover, the class TableBuilder could build an excel file for any Thing, as long as an implementation class of ThingEntry has been made. That's pretty sweet !
Maybe the only real "issue" I see with it is that 2n objects need to be created now, versus just the n of the 'ugly' implementation. But I feel that in 2018 that's not too big of an issue, right ?
A simple way to allow the internal representation of Worker to vary independently of the tabular representation of the Worker is to create a separate class for its representation. For example, given the following definition of Worker
public class Worker {
private final String firstName;
private final int age;
private final String job;
public Worker(String firstName, int age, String job) {
this.firstName = firstName;
this.age = age;
this.job = job;
}
public String getFirstName() {
return firstName;
}
public String getAge() {
return age;
}
public String getJob() {
return job;
}
}
the following wrapper can be created:
public interface TableEntry {
public List<String> getColumnValues();
}
public class WorkerTableEntry implements TableEntry {
private final Worker worker;
public WorkerEntry(Worker worker) {
this.worker = worker;
}
#Override
public List<String> getColumnValues() {
List<String> columns = new ArrayList<>();
columns.add(worker.getFirstName());
columns.add(String.valueOf(worker.getAge()));
columns.add(worker.getJob());
return columns;
}
}
This would now allow another class, TableBuilder to depend only on the TableEntry interface, not the internals of Worker:
public class TableBuilder {
public String buildTable(List<TableEntry> entries) {
// Print header
for (TableEntry entry: entries) {
List<String> columns = entry.getColumnValues();
// Print each column
}
}
}
Then the TableBuilder can be called as follows:
List<Worker> workers = ...
List<TableEntry> entries = new ArrayList<>();
for (Worker worker: workers) {
entries.add(new WorkerTableEntry(worker));
}
TableBuilder builder = new TableBulder();
builder.buildTable(entries);
This ensures that if the fields or methods of Worker change, its representation in the table does not necessarily change; and vice-versa, if the representation in the table needs to change, that the Worker class does not necessarily need to change (the two are independent). If other tables need to be built, you can simply create more implementations of TableEntry and reuse the TableBuilder class.
If you wanted to store the getters of the Worker class as the means of building the table, you can do so, although doing so is a bit more complicated. At its most basic level, the getters are Supplier<String> objects, meaning that take no arguments but produce a single String value. For example, you can develop a VariableTableEntry in the following manner:
public class VariableTableEntry {
private List<Supplier<String>> columnSuppliers;
public void addColumn(Supplier<String> supplier) {
columnSuppliers.add(supplier);
}
public String getRow() {
for (Supplier<String> columnSupplier: columnSuppliers) {
String columnValue = columnSupplier.get();
// Print each column
}
}
}
The difficult part is that not every getter will return a String. Some, like getAge(), will return an int. To be able to print those getter references as a String, a conversion would have to be performed (this method would be present in the VariableTableEntry class):
public void addIntColumn(Supplier<Integer> supplier) {
addColumn(() -> String.valueOf(supplier.get()));
}
This essential just wraps the supplied getter in a lambda expression that returns a String instead of an Integer/int. This process would be repeated for each of the other primitive values. Any Object (such as Worker) can be handled by deferring to toString:
public void addObjectColumn(Supplier<Object> supplier) {
addColumn(() -> supplier.get().toString());
}
If I have understood correctly, then Worker is your POJO and you are trying to create the list of POJOs and dumping in the excel sheet..So, what's the issue if person can add/remove the attributes in that bean class and corresponding getters/setters?
I have text file
Now I am trying to read this into a two dimension array .
anyone with an example code or question which was answered ?
Consider this file divided in middle present two record in same format, you need to design class that contains fields that you want to get from this file. After that you need to read
List<String> fileLines = Files.readAllLines(Path pathToYourFile, Charset cs);
and parse this file with help of regular expressions. To simplify this task you may read lines and after that specify regexp per line.
class UnstructuredFile {
private List<String> rawLines;
public UnstructuredFile (List<String> rawLines) {
this.rawLines = rawLines;
}
public List<FileRecord> readAllRecords() {
//determine where start and stop one record in list list.sublist(0,5) or split it to List<List<String>>
}
private FileRecord readOneRecord(List<String> record) {
//read one record from list
}
}
in this class we first detect start and end of every record and after that pass it to method that parse one FileRecord from List
Maybe you need to decouple you task even more, consider you have one record
------
data 1
data 2
data 3
------
we make to do classes RecordRowOne, RecordRowTwo etc. every class have regex that know how
to parse particular line of row of the record string and returns partucular results like
RecordRowOne {
//fields
public RecordRowOne(String regex, String dataToParse) {
//code
}
int getDataOne() {
//parse
}
}
another row class in example has methods like
getDataTwo();
after you create all this row classes pass them to FileRecord class
that get data from all Row classes and it will be present one record of you file;
class FileRecord {
//fields
public FileRecord(RecordRowOne one, RecordRowTwo two) {
//get all data from rows and set it to fields
}
//all getters for fields
}
it is basic idea for you
I'm stuck at the moment on a problem, I'm trying to add data separately to all objects in an array list.
eg. Daily, I want to be able to add how much medication each patient has taken to their record in the arraylist.
Each patient has a unique identifier which is whats in the arraylist.
I was wondering using JOptionPane is it possible to pull up each patient separately, so that after one is entered the next shows up to enter in information and how would I go about doing it?
Thanks!
Pseduo code of the data structure might be as following :
class Patient{
String patientId;
List<Medication> list;
public addMedication(Medication med){
list.add(med);
}
}
class Medication{
String name;
...
}
class PatientManager{
Map<String,Patient> map;
public addMedication(String patientId,Medication med){
map.get(patientId).addMedication(med);
}
}
I am designing a system which assembles disperate data in a standard row/column type output.
Each column can:
Exist in an independent system.
Can be paginated.
Can be sorted.
Each column can contain millions of rows.
And the system:
Needs to be extensible so different tables of different columns can be outputted.
The final domain object is known (the row).
The key is constant across all systems.
My current implementation plan is to design two classes per column (or one class column that implements two interfaces). The interfaces would:
Implement a pagination and sorting.
Implement "garnishing"
The idea is that the table constructor would receive information about the current sort column and page. Which would then return a list of appropriate keys for the table. This information would be used to create a list of the domain object rows which would then be passed in turn to each of the column "garnishing" implementations so that each columns information could be added in turn.
I guess my question is - what design patterns would be recommended - or alternative design decisions would people use for assembling disperate data with common keys and variable columns.
I'm not sure if I completely understood what you're trying to do, but from what I gather, you want to store rows of arbitrary data in a way that will allow you to make structured tables from it later on. What I would do in this case (assuming you're using Java) is make a very simple Column interface that would just have a "value" property:
public interface Column {
String value;
}
Then, you could make columns by implementing Column:
public class Key implements Column {
String value = new String();
public Key(String keyValue){
this.value = keyValue;
}
}
So then you can make a class called DataRow (or whatever you like) whose objects would contain the actual data. For example, you could have a method in that class that would allow you to add data:
public class DataRow {
List<Column> data = new ArrayList<Column>();
public DataRow(String key){
this.setColumn(new Key(key));
}
public void setColumn(Column columnData) {
this.data.add(columnData);
}
public Column getColumn(Class column){
for(Column c : this.data){
if(c.getClass().equals(column)){
return c;
}
}
return null;
}
}
As you can see, you can call the method setColumn() by giving it a new Column object. This will allow you to add any data you like of any type to the DataRow Object. Then, to make some tables, you could have a function that takes a List of DataRows, and a List of classes, that would then return only the objects which have data from the row specified:
public List<DataRow> createTable(List<DataRow> data, List<Class<? extends Column>> columns){
List<DataRow> table = new ArrayList<DataRow>();
for(DataRow row : data){
DataRow ret = new DataRow(row.getColumn(Key.class).value);
for(Class column : columns){
if(row.getColumn(column.getClass()) != null )ret.setColumn(row.getColumn(column.getClass()));
}
table.add(ret);
}
return table;
}
This will allow you to "create" tables using your data, and the columns you want to include in the table.
Note that I wrote this code to convey an idea, and that it's pretty messy at the moment. But I hope this will help you in some small way.
I'm trying to merge these three objects into a single complex object:
public class Person {
private String name;
private List<Event> events;
// getters and setters
}
public class Event {
private String name;
private List<Gift> gifts;
// getters and setters
}
public class Gift {
private String name;
private String recipient;// the name of the person
private String eventName;
// getters and setters
}
My goal is to save the Person object in MongoDB using Morphia and this how I want my document laid out. I've created a document builder, of sorts, that combines lists of each object. Each Person gets a list of all Events, but can only receive specific Gifts. While my document builder does create a document that Morphia can persist, only the Gifts of that last recipient (sort order) are inserted into the Events for all Persons. Though for the correct Events.
public void merge() {
for (Person person : listOfPersons) {
for (Event event : listOfEvents) {
// somePersonsGifts: a sublist of gifts based on Event and Person.
List<Gift> somePersonsGifts = new ArrayList<Gift>();
for (Gift gift : listOfGifts) {
if (person.getName().equals(gift.getRecipient()) && gift.getEventName().equals(event.getName())) {
somePersonsGifts.add(gift);
}
}
event.setGifts(somePersonsGifts);
}
person.setEvents(listOfEvents)
}
}
If I modify the code slightly to process one person at a time by removing the outer loop and having the method take an argument for specific index of the Persons list:
public void merge(int p) {
Person person = listOfPersons.get(p);
//...and so on
I get one complete Person object with the correct gifts. If try to feed the this modified version into a loop, the problem comes back. I've tried using regular for-loops and synchronized collections. I've tried using Google Guava's ImmutableArrayList and still no luck. I know the problem is that I'm changing the lists while accessing them but I can't find anyway around it. I wrote a DAO that uses the MongoDB driver directly and it works properly, but it's a lot more code and quite ugly. I really want this approach to work, the answer is in front of me but I just can't see it. Any help would be greatly appreciated.
Here is your problem:
List<Gift> somePersonsGifts = new ArrayList<Gift>();
....
event.setGifts(somePersonsGifts);
You add the gifts only for one person; if you want to aggregate all the gifts into the event, re-use the existing list.
I don't know anything about MongoDB or Morphia but I suspect the problem is your use of the setters event.setGifts(somePersonsGifts) and person.setEvents(events). Your code does not seem to merge the existing gift and event lists with the ones you are calculating further in the loop, which is how you would want it to behave (if I understand the question correctly).
You should retrieve the allready existing gift list (and event list too) instead of overwriting them with empty new ones.
I don't know if the method merge() is inside the list but I assume that since you are using the list events here
person.setEvents(events);
Maybe you meant
person.setEvents(listOfEvents)
Notice that you are adding all the events to each person. If all the persons went to all the events, it is unnecessary to have the events inside the person.