How to iterate through a list and match transactions - java
I am working on a project to upload my trades directly to an app I am building, by consuming a CSV file produced by my broker, instead of having to manually enter trades in a journal or paying for one.
My problem is that the data is represented as transactions not trades, therefore I have to match transactions (Buys/sells) and create another object from that. The reason I want to create a "Trade" Object is to store a list of them in a database and pass those objects to other methods to calculate stuff.
Here is what the data looks like from my broker:
Here is the Header for the CSV file:
Account,T/D,S/D,Currency,Type,Side,Symbol,Qty,Price,Exec Time,Comm,SEC,TAF,NSCC,Nasdaq,ECN Remove,ECN Add,Gross Proceeds,Net Proceeds,Clr Broker,Liq,Note
Sample data of the CSV file containing multiple examples of transactions:
FAKEACCOUNT,12/22/2020,12/23/2020,USD,2,B,MSFT201224P00222500,1,0.77,09:50:45,0.59,0,0,0.033,0.09,0,0,-77,-77.713,LAMP,,
FAKEACCOUNT,12/23/2020,12/24/2020,USD,2,S,MSFT201224P00222500,7,1.3,09:47:32,4.13,0.03,0.01,0.033,0.63,0,0,910,905.167,VOLANT,,
FAKEACCOUNT,12/24/2020,12/29/2020,USD,2,B,COCP,450,1.7,07:31:58,2.25,0,0,0.033,0.007065,0,0,-765,-767.290065,LAMP,e,
FAKEACCOUNT,12/24/2020,12/29/2020,USD,2,B,COCP,75,1.65,08:08:06,0.99,0,0,0.033,0.0011775,0,0,-123.75,-124.7741775,LAMP,X,
FAKEACCOUNT,12/24/2020,12/29/2020,USD,2,B,COCP,15,1.63,09:29:23,0.99,0,0,0.033,0.0002355,0,0,-24.45,-25.4732355,LAMP,,
FAKEACCOUNT,12/28/2020,12/30/2020,USD,2,S,COCP,540,1.4709,10:30:36,2.7,0.02,0.07,0.033,0.008478,0,0,794.286,791.454522,MNGD,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,B,PYPL210108P00235000,1,5.35,09:34:21,0.59,0,0,0.033,0.09,0,0,-535,-535.713,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,S,PYPL210108P00235000,1,5.95,09:36:47,0.59,0.02,0.01,0.033,0.09,0,0,595,594.257,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,B,NFLX201231P00535000,1,5.68,11:58:17,0.59,0,0,0.033,0.09,0,0,-568,-568.713,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,B,SPY201230P00372000,1,0.91,12:01:26,0.59,0,0,0.033,0.09,0,0,-91,-91.713,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,S,SPY201230P00372000,1,0.97,12:07:18,0.59,0.01,0.01,0.033,0.09,0,0,97,96.267,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,S,NFLX201231P00535000,1,6.02,12:21:55,0.59,0.02,0.01,0.033,0.09,0,0,602,601.257,VOLANT,,
Here, I matched the same transactions per color to better explain the concept. In yellow are two transactions forming 1 trade. The opening transaction is a "Buy" (B), therefore to close it, the matching transaction should be a "Sell" (S).
Same concept, slightly more complicated in green. The opening trade is a "Buy" with 450 as quantity. The subsequent transactions are also "Buy" with the same symbol, therefore adding to the position (450 + 75 + 15 = 540 quantity). A matching transaction to close the trade should be "Sell", but it could also be in increments. So I should keep track of quantity once a trade is initialized. See how the last green transaction is a sell of 540 quantity with the same symbol, bringing the total quantity to zero for the trade, meaning the trade is completed (Closed).
I have made a Transaction class with all the required fields, a constructor, getters and setters, as well as a Trade class.
public class Transaction {
private String account;
private LocalDate transactionDate;
private LocalDate settledDate;
private String currency;
private int type;
private char side;
private String symbol;
private int quantity;
private double price;
private LocalTime executionTime;
private double commission;
private double secFee;
private double tafFee;
private double nsccFee;
private double nasdaqFee;
private double ecnRemove;
private double ecnAdd;
private double grossProceeds;
private double netProceeds;
public Transaction(String account, LocalDate transactionDate, LocalDate settledDate, String currency,
int type, char side, String symbol, int quantity, double price, LocalTime executionTime,
double commission, double secFee, double tafFee, double nsccFee, double nasdaqFee,
double ecnRemove, double ecnAdd, double grossProceeds, double netProceeds) {
this.account = account;
this.transactionDate = transactionDate;
this.settledDate = settledDate;
this.currency = currency;
this.type = type;
this.side = side;
this.symbol = symbol;
this.quantity = quantity;
this.price = price;
this.executionTime = executionTime;
this.commission = commission;
this.secFee = secFee;
this.tafFee = tafFee;
this.nsccFee = nsccFee;
this.nasdaqFee = nasdaqFee;
this.ecnRemove = ecnRemove;
this.ecnAdd = ecnAdd;
this.grossProceeds = grossProceeds;
this.netProceeds = netProceeds;
}
// Getters, setters and toString()
}
Trade Class:
public Trade(String symbol, String side, LocalDate openDate, LocalTime openTime, LocalDate closeDate,
LocalTime closeTime,
double averageOpenPrice, int shares, double averageClosingPrice, double risk, String setup,
String comments) {
//Geting unique ID based on time
Date date = Calendar.getInstance().getTime();
this.id = date.getTime();
this.symbol = symbol;
this.side = side;
this.openDate = openDate;
this.openTime = openTime;
this.closeDate = closeDate;
this.closeTime = closeTime;
this.averageOpenPrice = averageOpenPrice;
this.shares = shares;
this.averageClosingPrice = averageClosingPrice;
this.risk = risk;
this.setup = setup;
this.comments = comments;
pnl = calculatePnL(averageOpenPrice, averageClosingPrice, shares, side);
percentGain = calculatePercentGain(averageOpenPrice, averageClosingPrice, side);
}
}
My problem: I am stuck at iterating through the list of transactions and matching them, for two reasons:
Sometimes I scale out of positions meaning that I do not sell in 1 transactions (Multiple transactions to close trades), which means I would have to match multiple transactions.
There is the possibility of a trade being still partially opened in the list passed. I do not know how to handle that possibility.
Symbol could either be a "Ticker" Symbol or an Option symbol, not sure if relevant.
What I have tried:
From the consumed file I get a list of Transaction objects, and I though I would match transactions by symbol, side (Buy/sell) and quantity. The problem with that approach is that it might not be the same trade.
public ObservableList<Trade> parseTradesFromTransactions(ObservableList<Transaction> list) {
for(Transaction transaction : list) {
int closedTradecount = 0;
// Iterating through the list
String symbol = transaction.getSymbol();
LocalDate transactionDate = transaction.getTransactionDate();
int quantity = transaction.getQuantity();
char side = transaction.getSide();
// iterate through the rest and match
for(int i = 0; i < list.size(); i ++) {
if(symbol.equals(list.get(i).getSymbol())){
if(transaction.getSide() == 'B' && list.get(i).getSide() == 'S' && transaction.getQuantity() == list.get(i).getQuantity()){
closedTradecount++;
}
}
}
}
return tradeList;
}
I am very new to programming and handling data, and I want to do this right. Any help would be greatly appreciated because I can't wrap my head around matching transactions.
Thanks!
If I understand your logic correctly, you would need 2 data structures in your program:
A dynamic array (suggest using ArrayList) to hold all closed trades you collected.
A dictionary / map (suggest using HashMap) to hold all open trades and access them quickly by their symbol.
Your algorithm would look like this:
Iterate over all transactions.
For each transaction, check if its symbol is in the open trades map.
--> If it is, add the transaction to the exisitng trade. Check if it reduces the amount of symbol to 0.
----> If symobol == 0, close the trade, and move it from the map to the closed trades list.
----> if symbol > 0, continue to next transaction.
--> If it is not, create a new trade for the symbol and add it to the map.
Once all trades are processed, the map should be empty, and you can store the list in your DB.
The code would look something like this:
public class TransactionProcessor {
private ArrayList<Trade> mClosedTrades = new ArrayList<>();
private HashMap<String, Trade> mOpenTrades = new HashMap<>();
public void processTransaction(Transaction transaction) {
Trade curTrade; //for convinience
if (!mOpenTrades.containsKey(transaction.getSymbol())) {
curTrade = new Trade(transaction);
mOpenTrades.add(transaction.getSymbol(), curTrade);
} else {
curTrade = mOpenTrades.get(transaction.getSymbol());
//shortcut: this function returns true if current transaction closes the trade:
if (curTrade.addTransaction(transaction)) {
mClosedTrades.add(curTrade);
mOpenTrades.remove(curTrade.getSymbol());
}
}
}
}
For this code to work, you need to add two more functions to your Trade class.
First, add a constructor to your Trade class that initializes it directly from the first transaction, instead of passing each parameter individually.
public Trade(Transaction first) {
symbol = first.getSymbol();
// ... all other fields initialization ...
}
Second, move the logic of adding further transactions to the trade class:
public boolean addTransaction(Transaction newTrans) {
//optional: add code that makes sure this transaction belongs to this trade by checking the symbol
if (newTrans.getSide() == 'B') {
quantity += newTrans.getQuantity();
} else {
quantity -= newTrans.getQuantity();
}
return quantity == 0; //this is same as if q == 0 return true; else return false;
}
This code assumes that transactions in your CSV file are in order, so that you would never need to open a new trade while you still have quantity of any particular symbol.
Also, there is no error checking.
If there are errors in the CSV file, you could end up with negative quantity of some symbol.
If you are having trouble adding such code, you should open a separate question about it.
For your first problem,
Sometimes I scale out of positions meaning that I do not sell in 1 transactions (Multiple transactions to close trades), which means I would have to match multiple transactions.
Use groupingBy method :
Group your transactions by 'symbol' and collect as map.
Map<Symbol, List> postsPerType = transactions.stream()
.collect(groupingBy(Transactions::getSymbol));
This way you get all transactions grouped together.
There is the possibility of a trade being still partially opened in the list passed. I do not know how to handle that possibility.
Iterate above collected transactions and match the quantity by filtering out Buy and Sell transactions to ensure whether trade is completed.
Related
How to specify a class property from a string in java
So I am reading from a file with scanner it has the similar format: title, name, age Mr, Matthew, 20 mr, Paul, 30 miss, Anne, 24 CSV^ class person{ String name, title; int age; public crimeData(String csv){ String[]list = csv.split(",", -1); name = list[0]; title = list[1]; age = list[2]; } } Console Program Scanner input = new Scanner(System.in); System.out.println("Please select what data you want to load:"); String selection = input.next(); int temp = 0; for(int i=0; i< header.length; i++){ if(header[i].equals(selection)){ temp = i; break; } } temp will give us the index of the option specified so if it is 2 we will want to access the age property When my console application runs I prompt them(the user) for the data that they want. So they may enter "age" So I am lost on how I may take this "age" String and access the person object with it. The ideal case for the program output should be: 20,30,24 going through each age and printing I take their input so String input = scanner.nextLine(); Then I loop through my array of person objects to get the index of the input. Once I have this index I then want to access the property of person at the index. So like if my index was 1 I would want to access the property 'name'. In javascript I could take the string and say person['age'] although java's a whole different story. I have looked into java's "reflection API" although it's a heavy learning curve.
I have looked into java's "reflection API" although it's a heavy learning curve. Well, Reflection is the way to go. It's widely used in many frameworks. But perhaps a simpler solution will fit your needs. Use a switch to decide which attribute to return, and encapsulate this in a method of the Person class: class Person { private String name, title; private int age; public loadData(String csv){ String[] list = csv.split(","); name = list[0]; title = list[1]; age = Integer.parseInt(list[2]); } public Object attribute(String attribute) { switch (attribute) { case "name": return this.name; case "title": return this.title; case "age": return this.age; default: throw new RuntimeException("Invalid attribute: " + attribute); } } } Encapsulating the switch inside the method is in line with OOP principles, since it hides how attributes are stored from other objects, only exposing an interface to query them. Reflection breaks all encapsulation.
Though in general I am not in favor of using Map for holding fields for an object, if the number of properties is large and could even potentially vary across CSV files (e.g., some file has the University a person attended, another does not), then using a Map to hold the properties might be appropriate. In this case, one would define a simple Person class: public class Person { Map<String, String> props = new HashMap<>(); public void addProperty(String propertyName, String value) { // could add error checking to ensure propertyName not null/emtpy props.put(propertyName, value); } /** * returns the value of the property; may return null */ public String getProperty(String propertyName) { return props.get(propertyName); } } If it is know that certain attributes/properties will always be loaded, then accessors such as getName() could be added: public String getName() { return props.get("name"); } public int getAge() { String age = props.get("age"); // or throw exception if missing return (age != null ? Integer.parseInt(age) : -1); } Though note I would expect name to not be a single entry for most datasets, as there typically would be last name, first name, etc. Nonetheless, the pattern for a limited number of commonly expected values is the same. Also, you can adapt so that you could get integer values directly for certain well-known fields. Then, when you parse the file, you keep the title row that has the attribute definitions. Then for each row that you subsequently read, you create a new Person object, and then add the properties in order. List<Person> allPersons = new ArrayList<>(); while ( (line = READ_NEXT_LINE) ) { // NOTE: this is not a safe way to handle CSV files; should really // use a CSV reader as fields could have embedded commas attrs[] = line.split(","); Person p = new Person(); for (int i = 0; i < titleRow.length; ++i) { p.addProperty(titleRow[i], attrs[i]); } allPersons.add(p); } You can then get a specific Person by Person myPerson = allPersons.get(index_of_person), and much akin to the way you would have used Javascript, you can do String val = myPerson.getProperty("age"). If you need to search by a given attribute, you can then stream/loop over the allPersons and check of equivalence based upon a given property. // find all people of a given age List<Person> peopleAge20 = allPersons.stream() .filter(p -> p.getAge() == 20) .collect(Collectors.toList()); System.out.println(peopleAge20); // summary statics (average age) for all people IntSummaryStatistics stats = allPersons.stream().mapToInt(p -> p.getAge()).summaryStatistics(); System.out.printf("Average age: %f\n", stats.getAverage()); Note that this approach does break the idea of a Javabean, but that may or may not be an issue depending upon your requirements.
First thing, we should add a constructor to your Person class. class Person { public Person(String name, String title, int age) { this.name = name; this.title = title; this.age = age; } } Now while you read the input you can use a Map as follows. Here after reading each line, we create a Person object and then using that person's age we make an entry in the map with key as age and value as Person. Map<Integer, Person> mapOfPeople = new HashMap<>(); while (input.hasNextLine()) { String line[] = input.nextLine().split(","); Perso person = new Perso(line[1], line[0], Integer.parseInt(line[2].trim())); mapOfPeople.put(person.getAge(), person); } Now to fetch a particular Person by age just do mapOfPeople.get(20);
How to Perform Percentage on item list Enum? [closed]
Closed. This question needs details or clarity. It is not currently accepting answers. Want to improve this question? Add details and clarify the problem by editing this post. Closed 4 years ago. Improve this question I'm looking for some tip on how to do a percentage thing for my game I want all flowers in a range of 1-98 and white/black flowers 99-100 to make it more rarerity thanks for the help :) public enum FlowerSuit { WHITE_FLOWERS("white", ":white:", "470419377456414720", 1), YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1 ), RED_FLOWERS("red", ":red:", "470419583250202644", 1), RAINBOW_FLOWERS("rainbow", ":rainbow:", "470419602841665536", 1), PASTEL_FLOWERS("pastel", ":pastel:", "470419629450199040", 1), ORANGE_FLOWERS("orange", ":orange:", "470419647900942366", 1), BLUE_FLOWERS("blue", ":blue:", "470419688753594368", 1), BLACK_FLOWERS("black", ":black:", "470419706751352842", 1); private final String displayName; private final String emoticon; private int value; private final String id; FlowerSuit(String displayName, String emoticon, String id, int value ) { this.displayName = displayName; this.emoticon = emoticon; this.value = value; this.id = id; } public String getDisplayName() { return displayName; } public String getEmoticon() { return emoticon; } public String getId() { return id; } public int getValue() { // TODO Auto-generated method stub return value; } }
This is how I'd do it, but it can probably be improved, for starters by using Java 8 streams etc. public enum FlowerSuit { WHITE_FLOWERS("white", ":white:", "470419377456414720", 1,3), YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1,2), RED_FLOWERS("red", ":red:", "470419583250202644", 1,2), RAINBOW_FLOWERS("rainbow", ":rainbow:", "470419602841665536", 1,2), PASTEL_FLOWERS("pastel", ":pastel:", "470419629450199040", 1,2), ORANGE_FLOWERS("orange", ":orange:", "470419647900942366", 1,2), BLUE_FLOWERS("blue", ":blue:", "470419688753594368", 1,2), BLACK_FLOWERS("black", ":black:", "470419706751352842", 1,1); private static Random random = new Random(); private final String displayName; private final String emoticon; private int value; private final String id; private final int freq; private FlowerSuit(String displayName, String emoticon, String id, int value, int freq ) { this.displayName = displayName; this.emoticon = emoticon; this.value = value; this.id = id; this.freq = freq; } public String getDisplayName() {return displayName;} public String getEmoticon() {return emoticon;} public String getId() {return id;} public int getValue() {return value;} /** * Choose a flower * white has a 3 in 16 (about a 5:1) chance of being picked * Black has a 1 in 16 chance, everything else 2/16 * #return */ public static FlowerSuit pick() { //first sum all the chances (currently it's 16) int sum = 0; for (FlowerSuit f:FlowerSuit.values()) sum+= f.freq; //now choose a random number int r = FlowerSuit.random.nextInt(sum) + 1; //now find out which flower to pick sum = 0; for (FlowerSuit f:FlowerSuit.values()) { sum += f.freq; if (r<=sum) return f; } //code will never get here return FlowerSuit.WHITE_FLOWERS; } public static void main(final String[] args) throws Exception { //Test it Map<FlowerSuit,Integer>count = new HashMap<FlowerSuit,Integer>(); for (int a=0;a<1000000;a++) { FlowerSuit f = FlowerSuit.pick(); Integer i = (count.get(f)!=null)?count.get(f):new Integer(0); i = new Integer(i+1); count.put(f,i); } int sum = 0; for (Map.Entry<FlowerSuit,Integer>e:count.entrySet()) sum+=e.getValue(); float f = Float.valueOf(sum); for (Map.Entry<FlowerSuit,Integer>e:count.entrySet()) { System.out.println(e.getKey() + " was chosen " + ((e.getValue() / f) * 100f) + "% of the time"); } } } gives BLUE_FLOWERS was chosen 12.4986% of the time PASTEL_FLOWERS was chosen 12.4707% of the time WHITE_FLOWERS was chosen 18.7365% of the time BLACK_FLOWERS was chosen 6.2632003% of the time ORANGE_FLOWERS was chosen 12.4986% of the time RED_FLOWERS was chosen 12.5241995% of the time YELLOW_FLOWERS was chosen 12.501401% of the time RAINBOW_FLOWERS was chosen 12.5068% of the time
You can use a TreeMap to map all of the integers from 0 to 99 to a particular FlowerSuit. Take advantage of the floorEntry method to choose a FlowerSuit for each number. It might look something like this. public class FlowerChooser { private static final NavigableMap<Integer, FlowerSuit> FLOWER_SUITS; private static final Random RANDOMS = new Random(); public FlowerChooser() { FLOWER_SUITS = new TreeMap<>(); FLOWER_SUITS.put(0, FlowerSuit.RED_FLOWERS); FLOWER_SUITS.put(14, FlowerSuit.ORANGE_FLOWERS); FLOWER_SUITS.put(28, FlowerSuit.YELLOW_FLOWERS); FLOWER_SUITS.put(42, FlowerSuit.GREEN_FLOWERS); FLOWER_SUITS.put(56, FlowerSuit.BLUE_FLOWERS); FLOWER_SUITS.put(70, FlowerSuit.INDIGO_FLOWERS); FLOWER_SUITS.put(84, FlowerSuit.VIOLET_FLOWERS); FLOWER_SUITS.put(98, FlowerSuit.WHITE_FLOWERS); FLOWER_SUITS.put(99, FlowerSuit.BLACK_FLOWERS); } public FlowerSuit randomFlowerSuit() { int index = RANDOMS.nextInt(100); return FLOWER_SUITS.floorEntry(index).getValue(); } } Create just one object of this class, then whenever you want a FlowerSuit, call the randomFlowerSuit method. The randomFlowerSuit method picks a random number from 0 to 99, then finds an appropriate entry in the map. The floorEntry method chooses an entry whose key is less than or equal to the chosen number. This means that numbers from 0 to 13 get mapped to red, 14 to 27 get mapped to orange, and so on. The only number that gets mapped to white is 98, and the only number that gets mapped to black is 99.
No matter what solution you implement, you want to include a frequency measure in your enum. As an example, you can do something like this: public enum FlowerSuit { WHITE_FLOWERS("white", ":white:", "470419377456414720", 1, 1), YELLOW_FLOWERS("yellow", ":yellow:", "470419561267855360", 1, 20), // More declarations here // Add this variable private final int frequency; // Do just as you did before in the constructor, but with the frequency FlowerSuit(String displayName, String emoticon, String id, int value, int frequency){ this.frequency = frequency; // More assignments here } public int getFrequency(){ return frequency; } // More getters here } This addition is critical, and no matter what method you use to weight flower selection, you will want this addition to your FlowerSuit enum. Now, we can explore a few different ways to perform this selection. Note 1: I use ThreadLocalRandom for random numbers in a range, which is from java.util.concurrent.ThreadLocalRandom. Note 2: For each of these, make a single instance of FlowerPicker, and use the pickFlower() method to pick the next flower. This avoid running costly setup code over and over. Method 1: Bag of Flowers This method is probably the easiest to implement. It entails creating a list of enums where each is represented frequency times, and then selecting a random entry from this list. It is similar to throwing a bunch of flowers in a bag, shaking it, and then reaching your hand in and grabbing the first flower you touch. Here's the implementation: public class FlowerPicker(){ private ArrayList<FlowerSuit> bag; public FlowerPicker(){ // Get all possible FlowerSuits FlowerSuit[] options = FlowerSuit.values(); // You can use an array here or an array list with a defined length if you know the total of the frequencies bag = new ArrayList<FlowerSuit>(); // Add each flower from options frequency times for (FlowerSuit flower : options) for (int i=0; i<flower.getFrequency(); i++) bag.add(flower); } public FlowerBag pickFlower(){ // Now, select a random flower from this list int randomIndex = ThreadLocalRandom.current().nextInt(0, bag.size()); return bag.get(randomIndex); } } This method has the advantage of being simple enough to understand very easily. However, it can be inefficient if your frequencies are extremely specific (like if you want a rainbow flower to be returned 499,999,999 times out of 1,000,000,000). Let's move on to the next method. Note 1: You could make this better by reducing the fractions representing the frequency of being chosen, but I'll leave this to you. Note 2: You could also make this slightly better by storing identification numbers, not FlowerSuit objects in the bag list. Method 2: Navigable Map This method is a little bit more difficult. It uses a [NavigableMap][1], which is an implementation of [TreeMap][2]. This method is fairly similar to the Bag of Flowers method, but it is a little bit more efficient. Put simply, it uses the TreeMap to give each FlowerSuit a range of numbers that can be selected to return that FlowerSuit. Here's a full example: public class FlowerPicker(){ private NavigableMap<Double, FlowerSuit> map; public FlowerPicker(){ // Get all possible FlowerSuits FlowerSuit[] options = FlowerSuit.values(); map = new TreeMap<Double, FlowerSuit>(); int runningTotal = 0; // Add each flower with the proper range for (FlowerSuit flower : options){ runningTotal += flower.getFrequency(); map.put(runningTotal, flower); } } public FlowerBag pickFlower(){ // Now, select a random number and get the flower with this number in its range int randomRange = ThreadLocalRandom.current().nextInt(0, bag.size()); return map.higherEntry(randomRange).getValue(); } } This is a solid method, and it scales well for very specific frequencies. If you have a bunch of different types of flowers, it will be slightly worse, but this method is still a good option at large scales. There's one more option though. Method 3: Enumerated Distribution This method is really nice because you barely have to do anything. However, it uses [EnumeratedDistribution][3] from Apache Commons. Enumerated Distribution requires a list of pairs of objects and weights. Anyway, lets jump into it: public class FlowerPicker(){ private EnumeratedDistribution distribution; public FlowerPicker(){ // Get all possible FlowerSuits FlowerSuit[] options = FlowerSuit.values(); List<Pair<FlowerSuit, Double>> weights = new List<Pair<FlowerSuit, Double>>(); // Add each flower and weight to the list for (FlowerSuit flower : options){ weights.add(new Pair(flower, flower.getFrequency())); // Construct the actual distribution distribution = new EnumeratedDistribution(weights); } public FlowerBag pickFlower(){ // Now, sample the distribution return distribution.sample(); } } This is my favorite method, simply because so much of it is done for you. Many problems like this have been solved, so why not use solutions that always exist? However, there is some value to writing the solution yourself. In conclusion, each of these methods are perfectly fine to use at your scale, but I would recommend the second or third method.
How to format Java ArrayList with respective rows and columns and invoke the data of a column or a row?
I am a Java beginner, I have been trying to read a csv file from my computer by using Java and insert the data into a ArrayList. public class DataRepository { public void loadFile(){ ArrayList<String> binsGrade = new ArrayList<String>(); try { Scanner fileScanner = new Scanner(new File("C:\\Users\\Max\\Desktop\\Grade_SampleData.csv")); while(fileScanner.hasNextLine()){ binsGrade.add(fileScanner.nextLine()); } fileScanner.close(); System.out.println(binsGrade); } catch (FileNotFoundException e){ e.printStackTrace(); } } } And below is the result I got: [name,literature,math,physics,chemistry,biology,history,geology,art,sports, Michael,80,90,82,79,75,70,72,68,95, Amy,85,88,73,79,88,93,90,92,75, Johnson,72,89,81,84,83,72,89,90,82, Bob,80,81,84,89,87,90,71,65,89, Tommy,70,89,79,90,88,73,75,89,91, Rachel,90,91,80,92,87,92,95,97,87, Evonne,78,91,87,88,91,76,74,86,91] All the records are in one row, but I actually want it to be in separated rows and columns, and for example, when I call name, I can get the value: Michael, Amy, Johson and etc. When I call literature, I can get 80, 85, 72, 80 and etc.Then I can probably use these data to do some calculation, like calculate the average, or get the maximum score and etc. Although I have been searching online for a while, I still have not figured out the best way to achieve this. Can you please share your ideas if you have one minute? Your help will be really appreciated. Thanks!
If you want to have something implemented quickly, you can follow Srivenu comment and use a Map<String, List<String>>. Each entry of the Map will have the name as the key, and a list of string for all the results. For example to add Michael : myMap.add("Michael", Arrays.asList({"20", "12", "8", "80"})); Then create the different methods that will go through this map to compute the average, or find the max, etc If you want a more oriented object approach I suggest you to create objects that will represent your data. First a result object that will contain two attributes, a string that will be the subject and an int that will be the score. public class Result { private String subject; private int score; public Result(String s, int i) { subject = s; score = i; } //Add Setters and Getters //Add additional method if required } Secondly Have a Person object that wil represent someone. It will have two attributes, a String representing the name and a list of Results objects. public class Person { private String name; private List<Result> results; public Person(String s, List<Result> r) { name = s; results = r; } //Add getters and setters //Add additional methods if required /** * Example of additional method * This one will return the score for a given subject **/ public int getScore(String subject) { Result r = results.get(subject); return r.getScore(); } } Thirdly, create a GroupOfPerson Class that will contain one attribute, a list of person. Then This class will have methods that will return the average, the max, etc... public class GroupOfPerson { private List<Person> persons; public GroupOfPErson(List<Person> p) { persons = p; } /** * Example of method. * This one will return the average score for the given subject **/ public int getAverageForSubject(String subject) { int average = 0; for(Person p : persons) { average += p.getScore(subject); } average /= persons.size(); return average; } //Add other methods } Finally when reading your CSV file, create the corresponding objects.
Using 2D parallel arrays to store data
I am supposed to let up to 16 guests order wine from a menu like this: The program has to be modular. To place an order, the guest must be shown a list of product types and then variations based on that type. Once the orders are processed I have to show a final report with: total amount made by the winery, most ordered wine product type, and the wine product/variation combo ordered the most times. I am not sure how to make a method that will search the counter array for the most ordered product type, and then another method that will search the counter array for the most ordered product/variation combo. That is what I need help with. import javax.swing.JOptionPane; public class Wine_Taste{ public static void main(String[] args){ String[]wines = {"Riesling", "Chardonnay", "Sauvignon Blanc", "Merlot"}; String[][]wineTypes= {{"Dry- $4.50", "Off Dry-$4.00", "Sweet- $5.00",}, {"Apple- $6.00", "Lemon-$5.50","Vanilla- $6.00"}, {"Lime-$4.50", "Lemongrass- $6.50","Coconut- $7.00"}, {"Plum- $5.00", "Black Cherry- $7.50","Chocolate- $6.00"}}; } double[][]prices= {{4.50, 4.00, 5.00}, {6.00, 5.50, 6.00}, {4.50, 6.50, 7.00}, {5.00, 7.50, 6.00}}; int[][]counter ={{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}}; counter = go(wines,wineTypes,counter,prices); public static int[][] go(String[] wines, String[][] wineTypes, int[][] counter, double[][] prices){ go2(counter); double totalCost = 0; String user; int x =0; while (x<=16){ for(int i = 0;i<wines.length;i++){ JOptionPane.showMessageDialog(null,wines[i]); } user = JOptionPane.showInputDialog("choose wine 0-3"); int i = Integer.parseInt(user); for(int j=0;j<wineTypes[i].length;j++){ JOptionPane.showMessageDialog(wineTypes[i][j]); } user = JOptionPane.showInputDialog("choose option 0-3"); int j = Integer.parseInt(user); totalCost += prices[i][j]; counter[i][j]++; user = JOptionPane.showInputDialog("Order more? y/n"); if (user.equals("y")){ x++; else{ JOptionPane.showMessageDialog(totalCost); } } } return counter; } } }
I wouldn't design the program like that. Following some basic object oriented dev principles you can have a wine class with a wine type, price etc, for example: public class Wine { String name; String type; double price; public Wine(String name, String type, double price) { super(); this.name = name; this.type = type; this.price = price; } //+getters setters } Then you can have an order class that keeps the order specific data, like which wine was ordered, the total price etc. If for any reason you want to keep using the approach of multiple (not easy to manage) arrays then I guess you can create a hashmap where the keys are the wine names and the values the popularity. You can increment by one when a new wine is ordered. You can increment as here: How to update a value, given a key in a java hashmap? If for any reason you don't want or can't use this approach then you can create two functions: getPopularProductVarCombo() for the most ordered type per wine, and getMostPopular() for the most popular of all. To implement getMostPopular you have to find the max value of the array. Here is a good example on how to do this Print largest number in a 2d array - why do my code print three numbers To implement getPopularProductVarCombo() then find the max value per line. Any other additional info you might need can be fetched in a similar way.
Retrieve data from list by the most recent date java
I'm trying to collect data from my list (or group) with the most recent date for example the last monday. So I could then add values together then insert the new values back into the list. Currently my output is looking like this ID Date charge balance 1 29/07/2013 10 100 2 29/07/2013 20 200 3 29/07/2013 30 300 Give or take a few columns. The main purpose is to group for example the entries that are the 29th, add the charge to the balance create a new entry / field / row with the new balance and the system date. So far I've create my list and I'm able to read in the entries from csv using a scanner but i have no idea how i can get the code to get the dates without hard coding. public class Statements { public int tncy_num; //public double net_rent; public String end_date; public double bal_val; public double chg_val; public Statements(int t, String ed, double bv , double cv){ tncy_num = t; //net_rent = nr; end_date = ed; bal_val = bv; chg_val= cv; } public int getTncynum(){return tncy_num;} //public double getNetRentnum(){return net_rent;} public String getEndDatenum(){return end_date;} public double getBalValnum(){return bal_val;} public double getChgValnum(){return chg_val;} //public double getBenfValnum(){return benf_val;} //public double getAdjVal(){return adj_val;} //public double getTotlValnum(){return totl_val;} public String toString(){ return " "+this.getTncynum()+ " "+this.getEndDatenum()+ " "+this.getBalValnum()+ " "+this.getChgValnum(); } } I have a main driver class which has the main method(used to simply run the script), a coordinator class used to get the data and set the location of the csv file and other classes which return the data of the list. public class Calculations { private Coordinator cord; private ArrayList Data; public Calculations(Coordinator co) { cord =co; Data = new ArrayList<Statements>(cord.getData()); System.out.print(Data); } }
Implement a Collections.Sort which sort your list, use JodaTime Library for Date http://joda-time.sourceforge.net/ Here an example : Collections.sort(myList, new Comparator<Statements>() { public int compare(Statements o1, Statements o2) { if (o1.getEndDate() == null || o2.getEndDate() == null) return 0; return o1.getEndDate().compareTo(o2.getEndDate()); } });