Java Hash map / Array List Count distinct values - java

I am pretty new into programming and I have an assignment to make, but I got stuck.
I have to implement a program which will read a CSV file (1 million+ lines) and count how many clients ordered "x" distinct products on a specific day.
The CSV looks like this:
Product Name | Product ID | Client ID | Date
Name 544 86 10/12/2017
Name 545 86 10/12/2017
Name 644 87 10/12/2017
Name 644 87 10/12/2017
Name 9857 801 10/12/2017
Name 3022 801 10/12/2017
Name 3021 801 10/12/2017
The result from my code is:
801: 2 - incorrect
86: 2 - correct
87: 2 - incorrect
Desired output is:
Client 1 (801): 3 distinct products
Client 2 (86): 2 distinct products
Client 3 (87): 1 distinct product
Additionally,
If I want to know how many clients ordered 2 distinct products I would like a result to look like this:
Total: 1 client ordered 2 distinct products
If I want to know the maximum number of distinct products ordered in a day, I would like the result to look like this:
The maximum number of distinct products ordered is: 3
I tried to use a Hash Map and Multimap by Google Guava (my best guess here), but I couldn't wrap my head around it.
My code looks like this:
package Test;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
public class Test {
public static void main(String[] args) {
//HashMultimap<String, String> myMultimap = HashMultimap.create();
Map<String, MutableInteger> map = new HashMap<String, MutableInteger>();
ArrayList<String> linesList = new ArrayList<>();
// Input of file which needs to be parsed
String csvFile = "file.csv";
BufferedReader csvReader;
// Data split by 'TAB' in CSV file
String csvSplitBy = "\t";
try {
// Read the CSV file into an ArrayList array for easy processing.
String line;
csvReader = new BufferedReader(new FileReader(csvFile));
while ((line = csvReader.readLine()) !=null) {
linesList.add(line);
}
csvReader.close();
} catch (IOException e) {
e.printStackTrace();
}
// Process each CSV file line which is now contained within
// the linesList list Array
for (int i = 0; i < linesList.size(); i++) {
String[] data = linesList.get(i).split(csvSplitBy);
String col2 = data[1];
String col3 = data[2];
String col4 = data[3];
// Determine if Column 4 has the desired date
// and count the values
if (col4.contains("10/12/2017")) {
String key = col3;
if (map.containsKey(key)) {
MutableInteger count = map.get(key);
count.set(count.get() + 1);
} else {
map.put(key, new MutableInteger(1));
}
}
}
for (final String k : map.keySet()) {
if (map.get(k).get() == 2) {
System.out.println(k + ": " + map.get(k).get());
}
}
}
}
Any advise or suggestion on how this can be implemented would be greatly appreciated.
Thank you in advance guys.

You could store a Setof productIds per clientId, and just take the size of that.
As a Set does not allow duplicate values, this will effectively give you the distinct number of productIds.
Also, I recommend that you give your variables meaningful name instead of col2, k, map... This will make your code more readable.
Map<String, Set<String>> distinctProductsPerClient = new HashMap<String, Set<String>>();
// Process each CSV file line which is now contained within
// the linesList list Array
// Start from 1 to skip the first line
for (int i = 1; i < linesList.size(); i++) {
String line = linesList.get(i);
String[] data = line.split(csvSplitBy);
String productId = data[1];
String clientId = data[2];
String date = data[3];
// Determine if Column 4 has the desired date
// and count the values
if (date.contains("10/12/2017")) {
if (!distinctProductsPerClient.containsKey(clientId)) {
distinctProductsPerClient.put(clientId, new HashSet<>());
}
distinctProductsPerClient.get(clientId).add(productId);
}
}
for (final String clientId : distinctProductsPerClient.keySet()) {
System.out.println(clientId + ": " + distinctProductsPerClient.get(clientId).size());
}
More advanced solution using Stream API (requires Java 9)
If you introduce the class OrderData(that represents a single line in the CSV) like this:
private static class OrderData {
private final String productName;
private final String productId;
private final String clientId;
private final String date;
public OrderData(String csvLine) {
String[] data = csvLine.split("\t");
this.productName = data[0];
this.productId = data[1];
this.clientId = data[2];
this.date = data[3];
}
public String getProductName() {
return productName;
}
public String getProductId() {
return productId;
}
public String getClientId() {
return clientId;
}
public String getDate() {
return date;
}
}
you can replace the for loop with this:
Map<String, Set<String>> distinctProductsPerClient2 = linesList.stream()
.skip(1)
.map(OrderData::new)
.collect(groupingBy(OrderData::getClientId, mapping(OrderData::getProductId, toSet())));
But I reckon this might be a little bit to complex if you're new into programming (although it might be a good exercise if you would try to understand what the above code does).

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.

Need an help to sort, Handle a tab seperated text file

Hi i have a text file(tab seperated).
I would like to open it, read it and filter the required columns just like we do in excel. Could someone help with a sample code.
I am stuck up with the concept on how to proceed further for the below steps.
Price has to sorted with DESC order before processing.
Always, First two column has to be printed in the output.
Other than the first two columns only the required column has to be printed based on the input given.
Input will be something like (Mango/purchased/top50). so it should pick only top50 "yet to buy" under "Mango" along with its respective first two columns.
Sample input file.
itemNumber Price Mango Apple Bannana
112201 purchased need to plan purchased
112202 55 yet to buy yet to buy purchased
112202 67 need to plan purchased purchased
112203 456 need to plan need to plan need to plan
112203 33 need to plan yet to buy need to plan
112204 456 need to plan yet to buy need to plan
112204 yet to buy purchased need to plan
112205 77 yet to buy purchased need to plan
112205 99 yet to buy purchased yet to buy
112206 0 yet to buy purchased yet to buy
The code is incomplete.
Here i am trying to add the heading of the file to an arraylist and adding the content to an another arraylist. Then trying to compare them using index number. Is this way correct ?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class main {
#SuppressWarnings({ "resource", "unused" })
public static void main(String[] args) throws IOException {
ZipFile zipFile = new ZipFile(
"filename.tsv.zip");
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
String fruit = "Mango";
String mappingstatus = "purchased";
// reading a file
ZipEntry entry = entries.nextElement();
InputStream stream = zipFile.getInputStream(entry);
InputStreamReader read = new InputStreamReader(stream);
BufferedReader br = new BufferedReader(read);
// creating a new list
List<String> heading = new ArrayList<String>();
String[] a = br.readLine().split("\t");
heading = Arrays.asList(a);
List<String> content = new ArrayList<String>();
String s;
while ((s = br.readLine()) != null) {
String[] b = br.readLine().split("\t");
content = Arrays.asList(b);
}
}
}
}
Try this
class Item implements Comparable<Item> {
int itemNumber;
int price;
String mango;
String apple;
String bannana;
public Item(int itemNumber, int price, String mango, String apple, String bannana) {
this.itemNumber = itemNumber;
this.price = price;
this.mango = mango;
this.apple = apple;
this.bannana = bannana;
}
//GETTERS
#Override
public int compareTo(Item compareItem) {
int comparePrice = ((Item) compareItem).getPrice();
//ascending order
//return this.price - comparePrice;
//descending order
return comparePrice - this.price;
}
}
public static void main(String[] args) {
List<Item> items = new ArrayList<>();
//populate the items list by creating an Item for every line you read.
//Handle null price values
Collections.sort(items);
//assuming input is some like 'Mango/purchased/top50'
String input = "Mango/purchased/top50";
String[] parts = input.split("/");
int max = Integer.parseInt(parts[2].substring(3));
List<Item> result = new ArrayList<>();
for (int i = 0; i < items.size() && result.size() < max; i++) {
Item item = items.get(i);
if ((parts[0].equals("Mango") && item.getMango().equals(parts[1]))
|| (parts[0].equals("Apple") && item.getApple().equals(parts[1]))
|| (parts[0].equals("Bannana") && item.getBannana().equals(parts[1]))) {
result.add(item);
}
}
}
Complete the commented sections and it must work. More references about sorting here: Sorting

manipulate and sort text file

I am working on a project where I have been given a text file and I have to add up the points for each team and printout the top 5 teams.
The text file looks like this:
FRAMae Berenice MEITE 455.455<br>
CHNKexin ZHANG 454.584<br>
UKRNatalia POPOVA 453.443<br>
GERNathalie WEINZIERL 452.162<br>
RUSEvgeny PLYUSHCHENKO 191.399<br>
CANPatrick CHAN 189.718<br>
CHNHan YAN 185.527<br>
CHNCheng & Hao 271.018<br>
ITAStefania & Ondrej 270.317<br>
USAMarissa & Simon 264.256<br>
GERMaylin & Daniel 260.825<br>
FRAFlorent AMODIO 179.936<br>
GERPeter LIEBERS 179.615<br>
JPNYuzuru HANYU 197.9810<br>
USAJeremy ABBOTT 165.654<br>
UKRYakov GODOROZHA 160.513<br>
GBRMatthew PARR 157.402<br>
ITAPaul Bonifacio PARKINSON 153.941<br>
RUSTatiana & Maxim 283.7910<br>
CANMeagan & Eric 273.109<br>
FRAVanessa & Morgan 257.454<br>
JPNNarumi & Ryuichi 246.563<br>
JPNCathy & Chris 352.003<br>
UKRSiobhan & Dmitri 349.192<br>
CHNXintong &Xun 347.881<br>
RUSYulia LIPNITSKAYA 472.9010<br>
ITACarolina KOSTNER 470.849<br>
JPNMao ASADA 464.078<br>
UKRJulia & Yuri 246.342<br>
GBRStacey & David 244.701<br>
USAMeryl &Charlie 375.9810<br>
CANTessa & Scott 372.989<br>
RUSEkaterina & Dmitri 370.278<br>
FRANathalie & Fabian 369.157<br>
ITAAnna & Luca 364.926<br>
GERNelli & Alexander 358.045<br>
GBRPenny & Nicholas 352.934<br>
USAAshley WAGNER 463.107<br>
CANKaetlyn OSMOND 462.546<br>
GBRJenna MCCORKELL 450.091<br>
The first three letters represent the team.
the rest of the text is the the competitors name.
The last digit is the score the competitor recived.
Code so far:
import java.util.Arrays;
public class project2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] array = new String[41];
String[] info = new String[41];
String[] stats = new String[41];
String[] team = new String[41];
//.txt file location
FileInput fileIn = new FileInput();
fileIn.openFile("C:\\Users\\O\\Desktop\\turn in\\team.txt");
// txt file to array
int i = 0;
String line = fileIn.readLine();
array[i] = line;
i++;
while (line != null) {
line = fileIn.readLine();
array[i] = line;
i++;
}
//Splitting up Info/team/score into seprate arrays
for (int j = 0; j < 40; j++) {
team[j] = array[j].substring(0, 3).trim();
info[j] = array[j].substring(3, 30).trim();
stats[j] = array[j].substring(36).trim();
}
// Random stuff i have been trying
System.out.println(team[1]);
System.out.println(info[1]);
System.out.println(stats[1]);
MyObject ob = new MyObject();
ob.setText(info[0]);
ob.setNumber(7, 23);
ob.setNumber(3, 456);
System.out.println("Text is " + ob.getText() + " and number 3 is " + ob.getNumber(7));
}
}
I'm pretty much stuck at this point because I am not sure how to add each teams score together.
This looks like homework... First of all you need to examine how you are parsing the strings in the file.
You're saying: the first 3 characters are the country, which looks correct, but then you set the info to the 4th through the 30th characters, which isn't correct. You need to dynamically figure out where that ends and the score begins. There is a space between the "info" and the "stats," knowing that you could use String's indexOf function. (http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(int))
Have a look at Maps.
A map is a collection that allows you to get data associated with a key in a very short time.
You can create a Map where the key is a country name, with value being the total points.
example:
Map<String,Integer> totalScore = new HashMap<>();
if (totalScore.containsKey("COUNTRYNAME"))
totalScore.put("COUNTRYNAME", totalScore.get("COUNTRYNAME") + playerScore)
else
totalScore.put("COUNTRYNAME",0)
This will add to the country score if the score exists, otherwise it will create a new totalScore for a country initialized to 0.
Not tested, but should give you some ideas:
public static void main(String... args)
throws Exception {
class Structure implements Comparable<Structure> {
private String team;
private String name;
private Double score;
public Structure(String team, String name, Double score) {
this.team = team;
this.name = name;
this.score = score;
}
public String getTeam() {
return team;
}
public String getName() {
return name;
}
public Double getScore() {
return score;
}
#Override
public int compareTo(Structure o) {
return this.score.compareTo(o.score);
}
}
File file = new File("path to your file");
List<String> lines = Files.readAllLines(Paths.get(file.toURI()), StandardCharsets.UTF_8);
Pattern p = Pattern.compile("(\\d+(?:\\.\\d+))");
List<Structure> structures = new ArrayList<Structure>();
for (String line : lines) {
Matcher m = p.matcher(line);
while (m.find()) {
String number = m.group(1);
String text = line.substring(0, line.indexOf(number) - 1);
double d = Double.parseDouble(number);
String team = text.substring(0, 3);
String name = text.substring(3, text.length());
structures.add(new Structure(team, name, d));
}
}
Collections.sort(structures);
List<Structure> topFive = structures.subList(0, 5);
for (Structure structure : topFive) {
System.out.println("Team: " + structure.getTeam());
System.out.println("Name: " + structure.getName());
System.out.println("Score: " + structure.getScore());
}
}
Just remove <br> from your file.
Loading file into memory
Your string splitting logic looks fine.
Create a class like PlayerData. Create one instance of that class for each row and set all the three fields into that using setters.
Keep adding the PlayerData objects into an array list.
Accumulating
Loop through the arraylist and accumulate the team scores into a hashmap. Create a Map to accumulate the team scores by mapping teamCode to totalScore.
Always store row data in a custom object for each row. String[] for each column is not a good way of holding data in general.
Take a look in File Utils. After that you can extract the content from last space character using String Utils e removing the <br> using it as a key for a TreeMap. Than you can have your itens ordered.
List<String> lines = FileUtils.readLines(yourFile);
Map<String, String> ordered = new TreeMap<>();
for (String s : lines) {
String[] split = s.split(" ");
String name = split[0].trim();
String rate = splt[1].trim().substring(0, key.length - 4);
ordered.put(rate, name);
}
Collection<String> rates = ordered.values(); //names ordered by rate
Of course that you need to adjust the snippet.

read a txt file and manipulate the readLine strings

I would like to take this format:
//Game, Team, Player, Position, Order, Sub----Not part of file
331027,24,7912,CF,1,1
331028,22,7913,P,1,1
331028,22,5909,1B,2,1
331028,22,8394,P,2,2
And display this data(order) based on a higher number for sub in a given order and the output will become:
331027,24,7912,CF,1 //player 7912 goes first for team 24
331028,22,7913,P,1 //player 7913 goes first for team 22
331028,22,8394,P,2 // player 8394 goes second for team 22 because he/she has higher 'Sub' order
UPDATE:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class BattingOrder {
String game_ID;
String team_ID;
String player_ID;
String position;
String battingOrder;
String subOrder;
public BattingOrder(String game, String team, String player, String place,
String batter, String sub) {
game_ID = game;
team_ID = team;
player_ID = player;
position = place;
battingOrder = batter;
subOrder = sub;
}
#Override
public String toString() {
return game_ID + "," + team_ID + "," + player_ID + "," + position + ","
+ battingOrder;
}
public static void main(String[] args) throws IOException {
FileInputStream fstream = new FileInputStream(
"BatterInfo.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
List<BattingOrder> sortList = new ArrayList<BattingOrder>();
for (String line; (line = br.readLine()) != null;) {
String delims = "[,]";
String[] parsedData = line.split(delims);
sortList.add(new BattingOrder(parsedData[0], parsedData[1],
parsedData[2], parsedData[3], parsedData[4], parsedData[5]));
}
for (BattingOrder order : sortList) {
System.out.println(order);
}
br.close();
}
}
Current Output:
331027,24,7912,CF,1
331028,22,7913,P,1
331028,22,5909,1B,2 //This should be replaced by bottom 'string' because the subOrder is higher.
331028,22,8394,P,2
I want:
331027,24,7912,CF,1
331028,22,7913,P,1
331028,22,8394,P,2
How might the logic look in pseudo-code?
From http://www.mkyong.com/java/how-to-sort-an-arraylist-in-java/ and http://www.mkyong.com/java/java-object-sorting-example-comparable-and-comparator/ and the above answer from Java Devil
I think the best method would be to put each BattingOrder object into a collection i.e. ArrayList and use Collections.sort
List<BattingOrder> unsortList = new ArrayList<BattingOrder>();
Add a constructor to BattingOrder or just manually set the values inside your for loop in main to either split the input string from the file or accept the preparsed values
then after the for loop is complete call Collections.sort and pass in a custom Comparator, you have most of the required code commented out should be no issue.
for (String line; (line = br.readLine()) != null;) {
// String delims = "[,]";
// String[] parsedData = line.split(delims);
//Split and assign the values to a new BattingOrder object here either in a
//constructor for BattingObject or here and pass in the values from the file
unsortList.add(new BattingOrder(line));
}
After the loop is complete call our custom sort function
Collections.sort(unsortList ,new Comparator<BattingOrder>(){
#Override
public int compare(BattingOrder one, BattingOrder two) {
Integer orderOne = Integer.parseInt(one.battingOrder);
Integer orderTwo = Integer.parseInt(two.battingOrder);
//ascending order
return orderOne.compareTo(orderTwo);
//descending order
//return orderTwo.compareTo(orderOne);
}
});
and bam should be sorted
I can't test this code atm at work no Java compiler but it should be close if not correct
Good luck ;)
Edit 3 (Clarification)
I was hoping you might add some more detail overnight, (Original input with index)
Index Pos Order Sub
1 CF 1 1
2 P 1 1
3 1B 2 1
4 P 2 2
Atm you don't have sufficient sort logic, disappearing index 3 is possible with the lower subOrder but 1 & 2 are interchangeable as they both have subOrder of 1 and order of 1 so whichever was read in first will be at the top of the list i think.
This code should sort them in some random order (Determined by the order they are read in by basically)
then will delete any that have a matching battingOrder and a lower subOrder
I hope thats close to what you want anyway the sort is pretty good just not great logic the delete isn't very efficient but its all I have to go on atm
All the casts could be removed by storing the integers as ints rather than strings
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class BattingOrder
{
String game_ID;
String team_ID;
String player_ID;
String position;
String battingOrder;
String subOrder;
public BattingOrder(String game, String team, String player, String place, String batter, String sub) {
game_ID = game;
team_ID = team;
player_ID = player;
position = place;
battingOrder = batter;
subOrder = sub;
}
#Override
public String toString()
{
return game_ID + "," + team_ID + "," + player_ID + "," + position + "," + battingOrder;
}
public static void main(String[] args) throws IOException
{
FileInputStream fstream = new FileInputStream("BatterInfo.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String delims = "[,]";
List<BattingOrder> battingOrders = new ArrayList<BattingOrder>();
for (String line; (line = br.readLine()) != null;)
{
String[] parsedData = line.split(delims);
battingOrders.add(new BattingOrder(parsedData[0], parsedData[1], parsedData[2], parsedData[3], parsedData[4], parsedData[5]));
}
br.close();
System.out.println("Unordered");
for (BattingOrder order : battingOrders)
{
System.out.println(order);
}
Collections.sort(battingOrders ,new Comparator<BattingOrder>(){
#Override
public int compare(BattingOrder one, BattingOrder two)
{
if(one.battingOrder.equals(two.battingOrder))
{
Integer subOrderOne = Integer.parseInt(one.subOrder);
Integer subOrderTwo = Integer.parseInt(two.subOrder);
return subOrderOne.compareTo(subOrderTwo);
}
Integer orderOne = Integer.parseInt(one.battingOrder);
Integer orderTwo = Integer.parseInt(two.battingOrder);
return orderOne.compareTo(orderTwo);
}
});
System.out.println("Ordered");
for (BattingOrder order : battingOrders)
{
System.out.println(order);
}
List<BattingOrder> toDelete = new ArrayList<BattingOrder>();
for (BattingOrder one : battingOrders)
{
for (BattingOrder two : battingOrders)
{
if(one.battingOrder.equals(two.battingOrder))
{
Integer subOrderOne = Integer.parseInt(one.subOrder);
Integer subOrderTwo = Integer.parseInt(two.subOrder);
if(subOrderOne < subOrderTwo)
{
toDelete.add(one);
}
else if(subOrderOne > subOrderTwo)
{
toDelete.add(two);
}
}
}
}
battingOrders.removeAll(toDelete);
System.out.println("Final");
for (BattingOrder order : battingOrders)
{
System.out.println(order);
}
}
}
You will need to read in all the lines from the text file first and then sort them.
As you read each line store it into a List of either Strings or better yet would be to create an object which represents each line - Which you pretty much have here already. So for each line you would want split by comma as you have comments and assign the values to a new instance of your object then add this to a list.
You can then sort the list using a comparator on these objects in the list using something like this
Collections.sort(yourList,new Comparator<BattingOrder>(){
#Override
public int compare(BattingOrder b1, BattingOrder b2)
{
//Your comparison code goes here
}
});

How to group the sorting of a file?

I'm trying to sort delimited files with a Time stamp | level | sensor name | measurement value structure so that all data associated with the sensor having the smallest time stamp would first be listed in increasing timestamp, then all the data associated with the sensor having the second smallest time stamp would be listed in increasing timestamp, etc…
Here’s an example of delimited file to be sorted :
20140102073500|1|sensor5|0.188|
20140102073502|1|sensor2|0.193|
20140102073600|2|sensor5|0.577|
20140102073603|2|sensor2|0.585|
20140102073700|3|sensor5|1.207|
20140102073702|3|sensor2|1.183|
Here what I want :
20140102073500|1|sensor5|0.188|
20140102073600|2|sensor5|0.577|
20140102073700|3|sensor5|1.207|
20140102073502|1|sensor2|0.193|
20140102073603|2|sensor2|0.585|
20140102073702|3|sensor2|1.183|
(note that I cannot sort by "sensor name / time stamp" because the sensor with the smallest time stamp changes from one file to the other...)
Here the coding I’m trying to work from (which only sort in ascending time stamp) :
import java.io.*;
import java.util.*;
public class Sort8 {
public static void main(String[] args) throws Exception {
Map<String, String> map;
try (BufferedReader reader = new BufferedReader(new FileReader("C:\\Test\\test.txt"))) {
map = new TreeMap<>();
String line;
while((line=reader.readLine())!=null){
map.put(getField(line),line);
System.out.println(getField(line));
}
System.out.println(map.values());
}
try (FileWriter writer = new FileWriter("C:\\Test\\test_sorted.txt")) {
for(String val : map.values()){
// System.out.println(val);
writer.write(val) ;
writer.write("\r\n");
}
}
}
private static String getField(String line) {
return ((line.split("\\|")[1])+(line.split("\\|")[3]));
}
}
I'm new to Java so thank in advance for the help you can provide !
Put a comparator in the construction of your tree map.
map = new TreeMap<>(new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
String[] a1 = s1.split("|");
String[] a2 = s2.split("|");
// First compare sensor
int sensor1 = Integer.parseInt(a1[2].replace("sensor", ""));
int sensor2 = Integer.parseInt(a2[2].replace("sensor", ""));
if(sensor1 != sensor2) {
return Integer.valueOf(sensor1).compareTo(sensor2);
}
// Second compare timestamp
long time1 = Long.parseLong(a1[0]);
long time2 = Long.parseLong(a2[0]);
return Long.valueOf(time1).compareTo(time2);
}
});

Categories

Resources