One of my methods is not working which I used with both map and java reflection. I am not sure is it because of reflection or any other reason but it is working in other class where I didn't use reflection.
The method findAccessors() should retrieve a value from map2. The method is defined in the class ReadEdges. This method is called by another method findmethod() which is defined in the class FindMethod.
Whenever I call the method findAccessors() by the method findmethod(), it is returning an empty Linked List instead of returning the value from map2. The classes are given below:
Class ReadEdges :
import java.io.BufferedReader;
import java.io.CharArrayReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import javax.swing.JOptionPane;
public class ReadEdges {
static DFSclass dfs = new DFSclass();
List<String> sourcenodes=new ArrayList<String>(); // source node
List<String> destinationnodes=new ArrayList<String>(); // destination node
LinkedHashSet<String> findtransitions=new LinkedHashSet<String>();
LoanApprovalSystem LS = new LoanApprovalSystem();
TestdataGeneration testdata = new TestdataGeneration();
private static final String edgePat = "([a-zA-Z]|[0-9])+(,|\\x20)([a-zA-Z]|[0-9])+";
private static final String start=dfs.getstart();
private static final String edge = dfs.getedge();
private static final String transitions=dfs.gettransitions();
public static String a;
public static String b;
public static String c;
public static String d;
private Map<String, LinkedHashSet<String>> map = new HashMap();
private Map<String, LinkedHashSet<String>> map2 = new HashMap();
public int getLineCount(String edge){
int count = edge.split("[\n|\r]").length;
//System.out.println(count);
return count;
}
public void addEdge(String node1, String node2) throws IOException{
LinkedHashSet<String> adjacent = map.get(node1);
{
if(adjacent==null) {
adjacent = new LinkedHashSet();
map.put(node1, adjacent);
}
adjacent.add(node2);
}
}
public void addedgeandAccessor(String edge, String accessor) throws IOException{
LinkedHashSet<String> adjacent2 = map2.get(edge);
{
if(adjacent2==null) {
adjacent2 = new LinkedHashSet();
map2.put(edge, adjacent2);
//System.out.println(map2);
}
adjacent2.add(accessor);
//System.out.println(map2);
}
}
public void ReadEdge(String edgeinput,String transitionsinput,String accessorinput) throws InvalidInputException
{
char[] buf = edgeinput.toCharArray();
BufferedReader br = new BufferedReader(new CharArrayReader(buf));
char[] buf2 = transitionsinput.toCharArray();
BufferedReader br2 = new BufferedReader(new CharArrayReader(buf2));
String str2 = null;
char[] buf3 = accessorinput.toCharArray();
BufferedReader br3 = new BufferedReader(new CharArrayReader(buf3));
String str3 = null;
try
{
//a string for a next edge
String str = null;
//a StringTokinizer
StringTokenizer newNodes = null;
//get edges and set edges for the graph
while((((str = br.readLine()) != null) && (str2 = br2.readLine()) != null) && ((str3 = br3.readLine()) != null))
{
c=str;
d=str2;
LinkedHashSet<String> adjacent = map.get(str);
if(adjacent==null) {
adjacent = new LinkedHashSet();
map.put(str, adjacent);
}
adjacent.add(str2);
addedgeandAccessor(str,str3);
//if the edge inputs are not in good format, throw the exception
if(!Pattern.matches(edgePat, str.trim()))
JOptionPane.showMessageDialog(null,"An invalid input '" + str + "' for an edge. Please read the notes above the forms. ");
//use a comma to separate tokens
newNodes = new StringTokenizer (str, ", ");
//get the value of source node of an edge
String src = newNodes.nextToken();
//create the source node and destination node
String srcNode = src;
String desNode = newNodes.nextToken();
a=srcNode;
b=desNode;
addEdge(srcNode, desNode);
//System.out.println(adjacent);
//findTransition(a,b);
//findAccessors(a,b);
}
//System.out.println(listoftransitions);
}
catch (IOException e) {
JOptionPane.showMessageDialog(null, "Something is Wrong!");
e.printStackTrace();
}
}
public LinkedList<String> adjacentNodes(String last) {
LinkedHashSet<String> adjacent = map.get(last);
if(adjacent==null) {
return new LinkedList();
}
return new LinkedList<String>(adjacent);
}
public LinkedList<String> findTransition(String node1, String node2) throws IOException{
LinkedHashSet<String> adjacent = map.get(node1+" "+node2);
if(adjacent==null) {
return new LinkedList();
}
findtransitions = adjacent;
return new LinkedList<String>(findtransitions);
}
public LinkedList<String> findAccessors(String node1, String node2) {
LinkedHashSet<String> adjacent = map2.get(node1+" "+node2);
if(adjacent==null) {
return new LinkedList();
}
System.out.println(adjacent);
return new LinkedList<String>(adjacent);
}
public String getsrcNode(){
return a;
}
public String getedgeline(){
return c;
}
public String gettransitionline(){
return d;
}
}
Class FindMethod :
import java.util.ArrayList;
import java.util.LinkedList;
import java.lang.reflect.*;
public class FindMethod {
ReadEdges r = new ReadEdges();
LoanApprovalSystem LS = new LoanApprovalSystem();
TestdataGeneration testdata = new TestdataGeneration();
int method1;
String method2;
boolean method3;
boolean method4;
String method5;
String m;
//returns the method name using refletion
public String getmethod(Method method){
FindMethod fm = new FindMethod();
m = method.getName();
String str = "";
str += m+"(" +fm.getparameter(method)+ ")";
// System.out.println(str);
return str;
}
//returns the parameter name of the method using refletion (i.e. (int))
public String getparameter(Method method){
String str = "";
Class<?>[] params = method.getParameterTypes();
for (int i = 0; i < params.length; i++) {
if (i > 0) {
str += ", ";
}
str += (params[i].getSimpleName());
}
return str;
}
public void findmethod(String s,String t,String transition) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
FindMethod fm = new FindMethod();
LoanApprovalSystem cls = new LoanApprovalSystem();
Class<? extends LoanApprovalSystem> c = cls.getClass();
Object obj = c.newInstance();
Method[] methods = LoanApprovalSystem.class.getMethods();
for(Method method : methods)
{
//returns the method name (i.e. Receive or Asses)
m = method.getName();
fm.getmethod(method);
if(transition.equals(fm.getmethod(method)) && (transition.equals("Receive(int)")) )
{
if(fm.getparameter(method).equals("int") )
{
//LS.Receive(testdata.TestData(s,t));
//invoking the method at runtime where m="Receive".
method = c.getMethod(m, int.class);
method.invoke(obj,testdata.TestData(s,t));
LinkedList<String> accessors= r.findAccessors(s,t);
System.out.println("A:"+accessors);
method1=LS.getamount();
System.out.println(m+"("+method1+")");
System.out.println("Amount: "+method1);
}
}
}
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException
{
FindMethod fm = new FindMethod();
fm.findmethod("1","2","Receive(int)");
}
}
Can anybody please tell me why my method findAccessors() is not working within the method findmethod()? Or please give me a solution of this problem.
Note: There is another class used in this program LoanApprovalSystem (). If anyone need I can give the definition of that class too.
It looks like you are calling the default constructor for ReadEdges:
'ReadEdges r = new ReadEdges();'
When you need to call your constructor that populates the maps:
'ReadEdges r = new ReadEdges(edgeinput, transitionsinput, accessorinput);'
EDIT:
The function
public void ReadEdge(String edgeinput, String transitionsinput, String accessorinput); is never being called.
You need to remove void and add as 's' to ReadEdge to make it a constructor:
public ReadEdges(String edgeinput, String transitionsinput, String accessorinput);
Then, when you instantiate ReadEdges in the FindMethod class, you need to supply the arguments.
ReadEdges r = new ReadEdges();
should be:
ReadEdges r = new ReadEdges(edgeinput, transitionsinput, accessorinput);
For more information, read about 'constructor overloading' and 'method overloading'. http://beginnersbook.com/2013/05/constructor-overloading/
Related
public static void main(String[] args)
{
ArrayList <Locations> LocationsList = readFile("Locations.csv", "Locations");
//ArrayList <Movies> MoviesList = readFile("Movies.csv", "Movies");
//ArrayList <Operators> OperatorsList = readFile("Operators.csv", "Operators");
//ArrayList <PersonCategory> PersonCategoryList = readFile("PersonCategory.csv", "PersonCategory");
}
public static ArrayList readFile(String fileName, String whichFile)
{
ArrayList list = new ArrayList();
try
{
BufferedReader br = new BufferedReader(new FileReader(fileName));
String indata;
int line = 0;
while((indata=br.readLine())!=null)
{
StringTokenizer st = new StringTokenizer(indata,",");
if(line != 0)
{
if(whichFile.equals("Locations"))
{
int id = Integer.parseInt(st.nextToken());
String city = st.nextToken();
if(city.charAt(0) == '"')
{
String c = st.nextToken();
city = city.substring(1,city.length()) +"," +c.substring(0,c.length()-1);
}
int stateId = Integer.parseInt(st.nextToken());
Locations x = new Locations(id, city, stateId);
list.add(x);
}
else if(whichFile.equals("Movies"))
{
int id = Integer.parseInt(st.nextToken());
String name = st.nextToken();
int ratingId = Integer.parseInt(st.nextToken());
Movies x = new Movies(id, name, ratingId);
list.add(x);
}
}
line++;
}
br.close();
}
catch (FileNotFoundException fnfe){System.out.println(fnfe.getMessage());}
catch (IOException io){System.out.println(io.getMessage());}
catch (Exception e){System.out.println(e.getMessage());}
return list;
}
I'm trying to create a method that will read a text file and can return an ArrayList type object for the usage of multiple Class. With my code above, it can run successfully.
But, there are lines of warning like:
"The expression of type ArrayList needs unchecked conversion to conform to ArrayList<Locations>"
How do I fix this?
Try this.
public static <T> ArrayList<T> readFile(String fileName, Function<String[], T> converter) throws IOException {
ArrayList<T> result = new ArrayList<>();
try (BufferedReader reader = Files.newBufferedReader(Paths.get(fileName))) {
String line = reader.readLine();
String[] fields = line.split(",");
T object = converter.apply(fields);
result.add(object);
}
return result;
}
and define the converters which convert a CSV line to an object.
static Locations convertLocations(String[] fields) {
int id = Integer.parseInt(fields[0]);
String city = fields[1];
if (city.charAt(0) == '"') {
String c = fields[2];
city = city.substring(1, city.length()) + "," + c.substring(0, c.length() - 1);
}
int stateId = Integer.parseInt(fields[3]);
Locations x = new Locations(id, city, stateId);
return x;
}
static Movies convertMovies(String[] fields) {
/* Make Movies object from fields */
}
and combine them.
ArrayList<Locations> LocationsList = readFile("Locations.csv", fields -> convertLocations(fields));
ArrayList<Movies> MoviesList = readFile("Movies.csv", fields -> convertMovies(fields));
You need to create the proper generics-based ArrayList using for example: new ArrayList<Location>()
You could solve this by passing a class to readFile like this:
public static <T> ArrayList<T> readFile(....., Class<T> clazz)
{
ArrayList<T> list = new ArrayList<T>();
...
}
This is my final code that I took from #saka1029 and made some adjustments so that it will read every line in the file except the first one.
public static <T> ArrayList<T> readFile(String fileName, Function<String[], T> converter)
{
ArrayList <T> list = new ArrayList<>();
try
{
BufferedReader br = new BufferedReader(new FileReader(fileName));
br.readLine();
String inData;
while((inData=br.readLine()) != null)
{
String[] fields = inData.split(",");
T object = converter.apply(fields);
list.add(object);
}
br.close();
}
catch (FileNotFoundException fnfe){System.out.println(fnfe.getMessage());}
catch (IOException io){System.out.println(io.getMessage());}
catch (Exception e){System.out.println(e.getMessage());}
return list;
}
And this is my version of the correction of the method convertLocations from #saka1029 answer.
static Locations convertLocations(String[] fields)
{
int id = Integer.parseInt(fields[0]);
String city = fields[1];
int stateId;
if (city.charAt(0) == '"')
{
String c = fields[2];
city = city.substring(1, city.length()) + "," + c.substring(0, c.length() - 1);
stateId = Integer.parseInt(fields[3]);
}
else
stateId = Integer.parseInt(fields[2]);
Locations x = new Locations(id, city, stateId);
return x;
}
Essentially, you need to specify the type parameter for generic class ArrayList.
Since you are adding objects created from different classes to the same list, you could create an interface, say, MyInterface
public interface MyInterface {
....
}
All classes you return from readFile must implement this interface. For eg.
public class Movies implements MyInterface {
....
}
Now, you can add type parameter MyInterface at appropriate places:
public static void main(String[] args) {
ArrayList<MyInterface> LocationsList = readFile("Locations.csv", "Locations");
....
}
public static ArrayList<MyInterface> readFile(String fileName, String whichFile) {
ArrayList<MyInterface> list = new ArrayList<>();
....
}
Added below info based on reply
You may in fact choose to leave the interface blank, but then you will have to explicitly cast objects to concrete classes to do anything useful.
You could cast each object when needed
MyInterface myInterfaceObject = locationsList.get(0)
Locations locations = Locations.class.cast(myInterfaceObject);
OR
MyInterface myInterfaceObject = locationsList.get(0)
Locations locations = (Locations) myInterfaceObject;
OR You could write a list converter function for each concrete type
public class ListConverter {
public ArrayList<Locations> toLocationsArraylist(ArrayList<MyInterface> inList) {
ArrayList<Locations> outList = new ArrayList<>();
for (MyInterface listItem : inList) {
outList.add((Locations) listItem);
}
return outList;
}
}
and then
public static void main(String[] args) {
ArrayList<MyInterface> myInterfaceList = readFile("Locations.csv", "Locations");
ArrayList<Locations> locationList = ListConverter.toLocationsArraylist(myInterfaceList);
}
If you do consider using this solution, then consider renaming MyInterface more appropriately, say, to CsvRecord, or anything domain-specific.
Can you tell me why I can't see my list when I try to start it from another method? Below methods:
public class CollectionsOperation {
private List<Client> bufferedReaderClientLIst = new ArrayList<Client>();
private List<Client> emptyBoxForCf = new ArrayList<Client>();
BufferedReader bf = null;
private static final String fileName = "Clients.txt";
public List<Client> bufferedReaderCollection() throws IOException {
String line;
bf = new BufferedReader(new InputStreamReader (new FileInputStream(fileName), "UTF-8"));
while((line = bf.readLine()) != null) {
String[] split = line.split(";");
String nameCompany = split[0].substring(2);
String adress = split[1];
String phoneNumber = split[2];
String emailAdress = split[3];
Client k = new Client(nameCompany, adress, phoneNumber, emailAdress);
bufferedReaderClientLIst.add(k);
}
System.out.println(bufferedReaderClientLIst);
return bufferedReaderClientLIst;
}
public void show() throws IOException {
CollectionsOperation k = new CollectionsOperation();
k.bufferedReaderCollection();
System.out.println(bufferedReaderClientLIst);
}
Calling the method:
public static void main(String[] args) throws IOException {
CollectionsOperation k = new CollectionsOperation();
k.show();
}
And this is the result what I get:
[ MarkCompany';Ilusiana';0982882902';mark#company.com, CorporationX';Berlin';93983';X#Corporation.com]
[]
Why the second list is empty ? the method bufferedReaderCollection() returns a result and the list bufferedReaderClientLIst is available to all methods. What is wrong?
In show():
public void show() throws IOException {
CollectionsOperation k = new CollectionsOperation();
k.bufferedReaderCollection();
System.out.println(bufferedReaderClientLIst);
}
You create another CollectionsOperation object to call bufferedReaderCollection() on. This is unnecessary.
However the problem is in the last print statement where you print bufferedReaderClientList. This is printing the bufferedReaderClientList of the this instance, not k. Because you have not called bufferedReaderCollection on this, the list will be empty, hence the [] printed at the end.
Instead of creating another instance, use this:
public void show() throws IOException {
this.bufferedReaderCollection();
System.out.println(bufferedReaderClientLIst);
}
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));
}
}
I am trying to save a javafx.scene.shape.Path to a file (at least its elements) however since Path is non-serializable and its PathElement as well it has proven very difficult.
Could someone inform me of a way to either convert the object to a String (preferred), JSON or something else?
Here are all the ways I have tried saving the object:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import javafx.scene.shape.Path;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
class Test {
public static void main(String[] args) {
GsonBuilder builder = new GsonBuilder();
Path path;
Gson gson = builder.create();
{
Rectangle rectangle = new Rectangle(100, 100);
Polygon polygon = new Polygon(0, 0, 50, 50, 0, 50);
path = (Path) Shape.subtract(rectangle, polygon);
}
try {
String completePathObject = gson.toJson(path);
System.out.println(completePathObject);
} catch (IllegalArgumentException e) {
e.printStackTrace();
// java.lang.IllegalArgumentException: class com.sun.javafx.util.WeakReferenceQueue$ListEntry declares multiple JSON fields named next
}
try {
String pathObjectElements = gson.toJson(path.getElements());
System.out.println(pathObjectElements);
} catch (IllegalArgumentException e) {
e.printStackTrace();
// java.lang.IllegalArgumentException: class com.sun.javafx.util.WeakReferenceQueue$ListEntry declares multiple JSON fields named next
}
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.set"))) {
objectOutputStream.writeObject(path);
} catch (IOException e) {
e.printStackTrace();
// java.io.NotSerializableException: javafx.scene.shape.Path
}
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.set"))) {
objectOutputStream.writeObject(path.getElements());
} catch (IOException e) {
e.printStackTrace();
// java.io.NotSerializableException: javafx.scene.shape.Path$2
}
}
}
Nodes contain a lot of properties you'd need to convert to a form that can be written to a file.
Since your last attempt indicates you'll be satisfied with writing the path elements to the file, you could convert the PathElements to parts of a SVG path and also implement logic for parsing the elements PathElements from a svg path string.
The following doesn't accept all possible SVG paths and may accept some invalid paths:
public class SVGConverter {
private enum PathElementType {
ARC('a', ArcTo.class, ArcTo::new,
ArcTo::radiusXProperty,
ArcTo::radiusYProperty,
ArcTo::XAxisRotationProperty,
ArcTo::largeArcFlagProperty,
ArcTo::sweepFlagProperty,
ArcTo::xProperty,
ArcTo::yProperty),
CLOSE_PATH('z', ClosePath.class, ClosePath::new),
CUBIC_CURVE('c', CubicCurveTo.class, CubicCurveTo::new,
CubicCurveTo::controlX1Property,
CubicCurveTo::controlY1Property,
CubicCurveTo::controlX2Property,
CubicCurveTo::controlY2Property,
CubicCurveTo::xProperty,
CubicCurveTo::yProperty),
H_LINE_TO('h', HLineTo.class, HLineTo::new,
HLineTo::xProperty),
LINE_TO('l', LineTo.class, LineTo::new,
LineTo::xProperty, LineTo::yProperty),
MOVE_TO('m', MoveTo.class, MoveTo::new,
MoveTo::xProperty, MoveTo::yProperty),
QUAD_CURVE_TO('q', QuadCurveTo.class, QuadCurveTo::new,
QuadCurveTo::controlXProperty, QuadCurveTo::controlYProperty,
QuadCurveTo::xProperty, QuadCurveTo::yProperty),
V_LINE_TO('v', VLineTo.class, VLineTo::new,
VLineTo::yProperty);
private final char letter;
private final String typeName;
private final Supplier<? extends PathElement> factory;
private final Function[] propertyGetters;
<T extends PathElement> PathElementType(char letter, Class<T> type, Supplier<T> factory, Function<T, ? extends Property<?>>... propertyGetters) {
this.letter = letter;
this.typeName = type.getName();
this.factory = factory;
this.propertyGetters = propertyGetters;
}
}
private final Map<String, PathElementType> ELEMENT_TYPES_BY_TYPE;
private final Map<Character, PathElementType> ELEMENT_TYPES_BY_LETTER;
public SVGConverter() {
ELEMENT_TYPES_BY_LETTER = new HashMap<>();
ELEMENT_TYPES_BY_TYPE = new HashMap<>();
for (PathElementType et : PathElementType.values()) {
ELEMENT_TYPES_BY_LETTER.put(et.letter, et);
ELEMENT_TYPES_BY_TYPE.put(et.typeName, et);
}
}
public String pathToSvg(Path path) {
StringBuilder sb = new StringBuilder();
for (PathElement element : path.getElements()) {
PathElementType elementType = ELEMENT_TYPES_BY_TYPE.get(element.getClass().getName());
if (elementType == null) {
throw new IllegalArgumentException("Unknown PathElement type: " + element.getClass().getName());
}
// specify path element type
char c = elementType.letter;
if (element.isAbsolute()) {
c = Character.toUpperCase(c);
}
sb.append(c);
// write property values
for (Function f : elementType.propertyGetters) {
Property property = (Property) f.apply(element);
sb.append((property instanceof BooleanProperty)
// special treatment for booleans to convert true/false to 1/0
? (((BooleanProperty) property).get() ? "1" : "0")
: property.getValue().toString()).append(' ');
}
}
// trim, if necessary
int lastIndex = sb.length() - 1;
if (lastIndex >= 0 && sb.charAt(lastIndex) == ' ') {
sb.deleteCharAt(lastIndex);
}
return sb.toString();
}
private static final String NUMBER_PATTERN_STRING = "[+-]?\\d*\\.\\d*(?:[eE][+-]?\\d+)?";
private static final Pattern NUMBER_PATTERN = Pattern.compile("(?<![\\d.+-])(" + NUMBER_PATTERN_STRING + ')');
private static final Pattern SVG_PATTERN = Pattern.compile("([aAcChHlLvmMqQVzZ])((?:\\s*" + NUMBER_PATTERN_STRING + "(?:[\\s,]+" + NUMBER_PATTERN_STRING + ")*)?)");
// parses doubles from number sequence
private static double[] getNumberMatches(Matcher m, int count) {
double[] result = new double[count];
for (int i = 0; i < count; i++) {
if (!m.find()) {
throw new IllegalArgumentException("missing numbers");
}
result[i] = Double.parseDouble(m.group(1));
}
if (m.find()) {
throw new IllegalArgumentException("too many numbers");
}
return result;
}
public Path svgToPath(String svg) {
Path path = new Path();
Matcher matcher = SVG_PATTERN.matcher(svg);
while (matcher.find()) {
// find out path element type
char c = matcher.group(1).charAt(0);
PathElementType elementType = ELEMENT_TYPES_BY_LETTER.get(Character.toLowerCase(c));
if (elementType == null) {
throw new IllegalArgumentException("Unknown path type " + c);
}
PathElement element = (PathElement) elementType.factory.get();
element.setAbsolute(Character.isUpperCase(c));
// retrieve parameters
if (elementType.propertyGetters.length > 0) {
Matcher numberMatcher = NUMBER_PATTERN.matcher(matcher.group(2));
double[] numbers = getNumberMatches(numberMatcher, elementType.propertyGetters.length);
for (int i = 0; i < elementType.propertyGetters.length; i++) {
Property property = (Property) elementType.propertyGetters[i].apply(element);
property.setValue((property instanceof BooleanProperty)
? (numbers[i] == 1) // convert to boolean (true iff 1.0)
: numbers[i]);
}
}
path.getElements().add(element);
}
return path;
}
}
Note: This does not restore any kind of bindings that may have existed before converting to string of course.
I have this textfile which I like to sort based on HC from the pair HC and P3
This is my file to be sorted (avgGen.txt):
7686.88,HC
20169.22,P3
7820.86,HC
19686.34,P3
6805.62,HC
17933.10,P3
Then my desired output into a new textfile (output.txt) is:
6805.62,HC
17933.10,P3
7686.88,HC
20169.22,P3
7820.86,HC
19686.34,P3
How can I sort the pairs HC and P3 from textfile where HC always appear for odd numbered index and P3 appear for even numbered index but I want the sorting to be ascending based on the HC value?
This is my code:
public class SortTest {
public static void main (String[] args) throws IOException{
ArrayList<Double> rows = new ArrayList<Double>();
ArrayList<String> convertString = new ArrayList<String>();
BufferedReader reader = new BufferedReader(new FileReader("avgGen.txt"));
String s;
while((s = reader.readLine())!=null){
String[] data = s.split(",");
double avg = Double.parseDouble(data[0]);
rows.add(avg);
}
Collections.sort(rows);
for (Double toStr : rows){
convertString.add(String.valueOf(toStr));
}
FileWriter writer = new FileWriter("output.txt");
for(String cur: convertString)
writer.write(cur +"\n");
reader.close();
writer.close();
}
}
Please help.
When you read from the input file, you essentially discarded the string values. You need to retain those string values and associate them with their corresponding double values for your purpose.
You can
wrap the double value and the string value into a class,
create the list using that class instead of the double value alone
Then sort the list based on the double value of the class using either a Comparator or make the class implement Comparable interface.
Print out both the double value and its associated string value, which are encapsulated within a class
Below is an example:
static class Item {
String str;
Double value;
public Item(String str, Double value) {
this.str = str;
this.value = value;
}
}
public static void main (String[] args) throws IOException {
ArrayList<Item> rows = new ArrayList<Item>();
BufferedReader reader = new BufferedReader(new FileReader("avgGen.txt"));
String s;
while((s = reader.readLine())!=null){
String[] data = s.split(",");
double avg = Double.parseDouble(data[0]);
rows.add(new Item(data[1], avg));
}
Collections.sort(rows, new Comparator<Item>() {
public int compare(Item o1, Item o2) {
if (o1.value < o2.value) {
return -1;
} else if (o1.value > o2.value) {
return 1;
}
return 0;
}
});
FileWriter writer = new FileWriter("output.txt");
for(Item cur: rows)
writer.write(cur.value + "," + cur.str + "\n");
reader.close();
writer.close();
}
When your program reads lines from the input file, it splits each line, stores the double portion, and discards the rest. This is because only data[0] is used, while data[1] is not part of any expression.
There are several ways of fixing this. One is to create an array of objects that have the double value and the whole string:
class StringWithSortKey {
public final double key;
public final String str;
public StringWithSortKey(String s) {
String[] data = s.split(",");
key = Double.parseDouble(data[0]);
str = s;
}
}
Create a list of objects of this class, sort them using a custom comparator or by implementing Comparable<StringWithSortKey> interface, and write out str members of sorted objects into the output file.
Define a Pojo or bean representing an well defined/organized/structured data type in the file:
class Pojo implements Comparable<Pojo> {
private double value;
private String name;
#Override
public String toString() {
return "Pojo [value=" + value + ", name=" + name + "]";
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* #param value
* #param name
*/
public Pojo(double value, String name) {
this.value = value;
this.name = name;
}
#Override
public int compareTo(Pojo o) {
return ((Double) this.value).compareTo(o.value);
}
}
then after that: read->sort->store:
public static void main(String[] args) throws IOException {
List<Pojo> pojoList = new ArrayList<>();
BufferedReader reader = new BufferedReader(new FileReader("chat.txt"));
String s;
String[] data;
while ((s = reader.readLine()) != null) {
data = s.split(",");
pojoList.add(new Pojo(Double.parseDouble(data[0]), data[1]));
}
Collections.sort(pojoList);
FileWriter writer = new FileWriter("output.txt");
for (Pojo cur : pojoList)
writer.write(cur.toString() + "\n");
reader.close();
writer.close();
}
Using java-8, there is an easy way of performing this.
public static void main(String[] args) throws IOException {
List<String> lines =
Files.lines(Paths.get("D:\\avgGen.txt"))
.sorted((a, b) -> Integer.compare(Integer.parseInt(a.substring(0,a.indexOf('.'))), Integer.parseInt(b.substring(0,b.indexOf('.')))))
.collect(Collectors.toList());
Files.write(Paths.get("D:\\newFile.txt"), lines);
}
Even better, using a Method reference
public static void main(String[] args) throws IOException {
Files.write(Paths.get("D:\\newFile.txt"),
Files.lines(Paths.get("D:\\avgGen.txt"))
.sorted(Test::compareTheStrings)
.collect(Collectors.toList()));
}
public static int compareTheStrings(String a, String b) {
return Integer.compare(Integer.parseInt(a.substring(0,a.indexOf('.'))), Integer.parseInt(b.substring(0,b.indexOf('.'))));
}
By using double loop sort the items
then just comapre it using the loop and right in the sorted order
public static void main(String[] args) throws IOException {
ArrayList<Double> rows = new ArrayList<Double>();
ArrayList<String> convertString = new ArrayList<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("C:/Temp/AvgGen.txt"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String s;
try {
while((s = reader.readLine())!=null){
String[] data = s.split(",");
convertString.add(s);
double avg = Double.parseDouble(data[0]);
rows.add(avg);
}
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileWriter writer = new FileWriter("C:/Temp/output.txt");;
Collections.sort(rows);
for (double sorted : rows) {
for (String value : convertString) {
if(Double.parseDouble(value.split(",")[0])==sorted)
{
writer.write(value +"\n");
}
}
}