How to convert the string back to object? I have the following class:
class Test {
String name;
String value;
String testing;
#Override
public String toString() {
return "Test{" +
"name='" + name + '\'' +
", value='" + value + '\'' +
", testing='" + testing + '\'' +
'}';
}
}
class Testing {
private List<Test> testing = new ArrayList<Test>();
handling(testing.toString())
public String handling(String testing) {
// do some handling and return a string
}
}
ArrayList testing must handled by convert to string, for example, after that, we get the following string:
[Test{name='name1', value='value1', testing='testing1'}, Test{name='name2', value='value2', testing='testing2'}, Test{name='name3', value='value3', testing='testing3'}]
then how to convert the string back to object list of Test?
Can anyone help on it?
If you don't need exactly that toString pattern, but only need to convert your Object to something human-readable and than back to an Object, you could marshal to json and parse back to Object seamlessly with something like Jackson ObjectMapper. See https://www.baeldung.com/jackson-object-mapper-tutorial for a quick-start.
You can create an additional constructor and call them with the string:
class Test {
private String name;
private String value;
private String testing;
Test(string objString) {
Pattern pattern = Pattern.compile("name=('.+'), value=('.+'), testing=('.+')");
Matcher matcher = pattern.matcher(objString);
if (matcher.matches()) {
name = matcher.group(1);
value = matcher.group(2);
testing = matcher.group(3);
} else {
throw new ArgumentException("Cannot parse"):
}
}
#Override
public String toString() {
return "Test{" +
"name='" + name + "'" +
", value='" + value + "'" +
", testing='" + testing + "'" +
'}';
}
}
class Testing {
doTesting(List<Test> testing) {
List<String> testingAsString = new ArrayList<String>();
// To string
for (Test t : testing) {
testingAsString.add(t.toString());
}
List<Test> clonedTesting = new ArrayList<Test>();
// To Test
for (String t : testingAsString) {
clonedTesting.add(new Test(t));
}
// Here every test string is again an object of type Test
for (Test t : clonedTesting) {
System.out.println(t);
}
}
}
Related
I have two lists with with the same data except the first list might have slightly different wording.
I am making sure the fields dont match. If they dont, then i add a plus to the first word in the array and a minus to the second word in the second array.
I am just iterating over the list and i have a ton of ifs. There are other data points i will need to do also and the ifs can get very long. Is there a more efficient way of doing this?
I am not good with java 8+ and streams. Would it be better to do it with streams and if so how would i do this? Could you please do an example?
Thank you in advance!!! I really need help but i am expecting to get my heart broken!
List<ExteriorColor> f1 = vinResponseOne.getResult().getExteriorColors();
List<ExteriorColor> f2 = vinResponseTwo.getResult().getExteriorColors();
first = vinResponseOne.getResult().getExteriorColors();
second = vinResponseTwo.getResult().getExteriorColors();
private void compareExteriorColors(List<ExteriorColor> f1, List<ExteriorColor> f2){
for(int i =0; i< f1.size(); i++) {
if (!f1.get(i).getDescription().equals(f2.get(i).getDescription())) {
final String added = "+ " + f1.get(i).getDescription();
final String original = "- " + f2.get(i).getDescription();
first.get(i).setDescription(added);
second.get(i).setDescription(original);
}
if (!f1.get(i).getGenericDesc().equals(f2.get(i).getGenericDesc())) {
final String added = "+ " + f1.get(i).getGenericDesc();
final String original = "- " + f2.get(i).getGenericDesc();
first.get(i).setGenericDesc(added);
second.get(i).setGenericDesc(original);
}
if (!f1.get(i).getColorCode().equals(f2.get(i).getColorCode())) {
final String added = "+ " + f1.get(i).getColorCode();
final String original = "- " + f2.get(i).getColorCode();
f1.get(i).setColorCode(added);
f2.get(i).setColorCode(original);
}
if (f1.get(i).getInstallCause() != null) {
if (!f1.get(i).getInstallCause().equals(f2.get(i).getInstallCause())) {
final String added = "+ " + f1.get(i).getInstallCause();
final String original = "- " + f2.get(i).getInstallCause();
first.get(i).setInstallCause(added);
second.get(i).setInstallCause(original);
}
}
if (!f1.get(i).getPrimary().equals(f2.get(i).getPrimary())) {
final String added = "+ " + f1.get(i).getPrimary();
final String original = "- " + f2.get(i).getPrimary();
first.get(i).setPrimary(added);
second.get(i).setPrimary(original);
}
if (!f1.get(i).getRgbValue().equals(f2.get(i).getRgbValue())) {
final String added = "+ " + f1.get(i).getRgbValue();
final String original = "- " + f2.get(i).getRgbValue();
first.get(i).setRgbValue(added);
second.get(i).setRgbValue(original);
}
if (!f1.get(i).getStyles().equals(f2.get(i).getStyles())) {
List<String> styleFirst = new ArrayList<>();
List<String> styleSecond = new ArrayList<>();
final String added = "+ " + f1.get(i).getStyles();
final String original = "- " + f2.get(i).getStyles();
styleFirst.add(added);
styleSecond.add(original);
first.get(i).setStyles(styleFirst);
second.get(i).setStyles(styleSecond);
}
if (!f1.get(i).getType().equals(f2.get(i).getType())) {
String added = "+ " + f1.get(i).getType();
String original = "- " + f2.get(i).getType();
first.get(i).setType(added);
second.get(i).setType(original);
}
}
}
What it ends up looking like.
I will later convert to json.
class User { //Considering a simple class with only 2 fields for brevity
private String userName;
private String password;
User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String toString() {
return "User{" + "userName='" + userName + '\'' + ", password='" + password + '\'' + '}';
}
}
public class S14 {
public static void main(String[] args) {
User user1 = new User("Anees", "pwd");
User user2 = new User("Anees1", "pwd");
List<User> userList1 = new ArrayList<>(Arrays.asList(user1, user2));
User user3 = new User("Anees2", "pwd");
User user4 = new User("Anees3", "pwd");
List<User> userList2 = new ArrayList<>(Arrays.asList(user3, user4));
// Assuming both Lists are of same size
IntStream.range(0, userList1.size())
.forEach(
i -> {
User firstListUser = userList1.get(i);
User secondListUser = userList2.get(i);
//HERE GOES THE MAIN PART
compareStringsAndProcessElement(
firstListUser::getUserName,
secondListUser::getUserName,
(s, s2) -> !s.equals(s2),
firstListUser::setUserName,
secondListUser::setUserName);
compareStringsAndProcessElement(
firstListUser::getPassword,
secondListUser::getPassword,
(s, s2) -> !s.equals(s2),
firstListUser::setPassword,
secondListUser::setPassword);
//AND SO ON!
});
System.out.println(userList1);
System.out.println(userList2);
}
private static void compareStringsAndProcessElement(
Supplier<String> element1,
Supplier<String> element2,
BiPredicate<String, String> stringStringBiPredicate,
Consumer<String> u1,
Consumer<String> u2) {
String e1 = element1.get();
String e2 = element2.get();
if (stringStringBiPredicate.test(e1, e2)) {
e1 = "+" + e1;
e2 = "-" + e2;
u1.accept(e1);
u2.accept(e2);
}
}
}
Hope this helps! This has nothing fancy with Streams, but uses Functional approach for a problem instead of your declarative one. This could be written with Normal loops too instead of IntStream.
PS: As far as performance goes, this might be even slower than declarative implementation since it involves multiple method calls. But, saving off some nanoseconds is not a good trade-off than code maintainability.
I have an abstract superclass that has two attributes: int and string. I have overridden the toString method in it as well as in its subclass that has one extra attribute (LocalDate). However, for some reason that I don't understand, when I print the subclass toSring info, the int value changes.
This is what I have in the superclass:
public abstract class File {
private int id;
private String text;
public File(int newId, String newText) throws IllegalArgumentException {
id(newId);
text(newText);
}
public int id() {
return id;
}
public void id(int e) throws IllegalArgumentException {
if (e <= 0) {
throw new IllegalArgumentException();
}
else {
id = e;
}
}
public String text() {
return text;
}
public void text(String aText) throws IllegalArgumentException {
if (aText == null || aText.length() == 0) {
throw new IllegalArgumentException();
}
else {
text = aText;
}
}
#Override
public String toString() {
return '"' + id() + " - " + text() + '"';
}
Then in the subclass I have this:
public class DatedFile extends File {
private LocalDate date;
public DatedFile (int newId, LocalDate newDate, String newText) throws IllegalArgumentException {
super(newId, newText);
date(newDate);
}
public LocalDate date() {
return date;
}
public void date(LocalDate aDate) throws IllegalArgumentException {
if (aDate == null) {
throw new IllegalArgumentException();
}
else {
date = aDate;
}
}
#Override
public String toString() {
return '"' + id() + " - " + date + " - " + text() + '"';
}
I tested it like this:
public static void main(String[] args) {
LocalDate when = LocalDate.of(2020, 1, 1);
DatedFile datedFile1 = new DatedFile(999, when, "Insert text here");
System.out.println(datedFile1);
It printed: "1033 - 2020-01-01 - Insert text here"
However, if i use the following code
System.out.println(datedFile1.id());
it prints the correct id (999). So I assume that something with the toString messes it up, but I have no idea where the problem is.
PS. I'm a beginner and I'm sorry if I included too much code but as I don't know what is the problem, I really don't know what is relevant and what isn't.
Your problem is here:
return '"' + id() + " - " + date + " - " + text() + '"';
id() returns an int, and '"' is a char, which is a numeric type. So '"' + 999 is 1033, not "999.
To fix the problem, use a String instead of a character:
return "\"" + id() + " - " + date + " - " + text() + "\"";
Change your toString() method from '"' to " \"".
'"' is a character (which is stored internally as an Integer), so adding it with id() produces the result you're seeing.
or using string interpolation:
return '\" ${id()} - ${date} - ${text()} \"';
I have to write a PhonePlan object that will represent the type of plan that a customer has for his/her phone. So the object must keep track of the minutesAllowed (int), minutes used (int), dataAllowed (int), data used (int) and planType (boolean):
public class PhonePlan {
int minutesAllowed;
int minutesUsed;
int dataAllowed;
int dataUsed;
boolean planType;
}
I needed to write a constructor which has minutesAllowed, dataAllowed, and the planType as arguments which I did:
public PhonePlan (int ma, int da, boolean pt){
this.minutesAllowed = ma;
this.planType = pt;
this.dataAllowed = da;
}
And finally I have to write a string method that displays the plan depending on the type of plan.
I also have to test my code with the following test program;
public class PlanTestProgram {
public static void main(String args[]) {
System.out.println(new PhonePlan(200, 2500000, false));
System.out.println(new PhonePlan(250, 500000, true));
System.out.println(new PhonePlan(300, 5000000, false));
System.out.println(new PhonePlan(60, 1000000, false));
System.out.println(new PhonePlan(30, 0, true));
}
The first element being the minutesAllowed, the second one being the amount of dataAllowed and the third one is stating if planType is true of false.
I tried many different things but I am not able to construct a toString() method that take into account if my planType is either true or false...
My Attempt:
public String toString(){
return ( "Regular(" + minutesAllowed + " minute," + dataAllowed
+ "GB data) Monthly Plan with "
+ getMinutesRemaining() + " minutes remaining and "
+ getDataRemaining() + "KB remaining");
}
You can easily update return in your suggested (attempt) toString method, by using the shorthand if/else, into the following:
return ("Regular(" + minutesAllowed + " minute," + dataAllowed
+ "GB data) " + ((PlanType)? "Monthly": "Annual") + " Plan with "
+ getMinutesRemaining() + " minutes remaining and "
+ getDataRemaining() + "KB remaining");
Metod toString() should never be used to showcase the value of the object properties. For the overrides you can use commons library
public String toString() {
return new ToStringBuilder(this).
append("minutesAllowed", minutesAllowed).
append("minutesUsed", minutesUsed).
append("dataAllowed", dataAllowed).
append("dataUsed", dataUsed).
append("planType", planType).
toString();
}
you could implement the toString method as described in the following code
public class PhonePlan {
int minutesAllowed;
int minutesUsed;
int dataAllowed;
int dataUsed;
boolean planType;
public PhonePlan (int ma, int da, boolean pt){
this.minutesAllowed = ma;
this.planType = pt;
this.dataAllowed = da;
}
#Override
public String toString() {
return planType ? getPlanTypeBasedString("Weekly Plan") : getPlanTypeBasedString("Monthly Plan");
}
public String getPlanTypeBasedString(String planType){
return ( "Regular(" + minutesAllowed + " minute," + dataAllowed
+ "GB data) "+planType+" with "
+ getMinutesRemaining() + " minutes remaining and "
+ getDataRemaining() + "KB remaining");
}
I'm having trouble using a method from a class that I have written. The following method was added to a class I created named Course. The goal is to write all of the properties of the object on one line as a String.
// method to return properties as a CSV string on one line
public String toCSVString(Course c) {
String record = c.campus + ","
+ c.course + ","
+ c.section + ","
+ c.crn + ","
+ c.credits + ","
+ c.time + ","
+ c.days + "\n";
return record;
} //end toCSVString()
OK, so after adding that method to the Class. I then began to create a method (which is called from the main method) needed to write from a Course array to a CSV File which calls the above method. This is the method I wrote.
// add a method here to write from an array of courses to a CSV file
public static void writeCSV(Course[] courseArray, int count) throws Exception {
//create a File class object and give the file the name employees.csv
java.io.File courseCSV = new java.io.File("courses.csv");
//Create a Printwriter text output stream and link it to the CSV File
java.io.PrintWriter outfile = new java.io.PrintWriter(courseCSV);
//Iterate the elements actually being used
for (int i=0; i < count ; i++) {
outfile.write(courseArray.toCSVString(courseArray[i]));
}//end for
outfile.close();
} //end writeCSV()
I'm having trouble with the line that starts with "outfile.write"
In my code, I am having trouble getting Netbeans to locate the toCSVString method which is defined after the toString method in the Course class. Originally that line in the code looked like this:
outfile.write(toCSVString(courseArray[i]));
But my IDE could not find it so I added the instance of the course object in front of it. However, I am still having trouble.
Does anybody see what I am doing wrong?
EDIT #1
Here is the Course class in my program. I am having issues with the toCSVString method.
class Course implements Serializable {
private String campus; // the campus on which the course is offered
private String course; // the course number, such as CSCI 111
private String section; // the section number
private String crn; // the CRN for this section
private int credits; // the number od credits for the course
private String time; // the time the course is offered, such as 8:00 to 10:00 A.M.
private String days; // the Days the course is offered, suhc as MW
// constructors
Course() {
}
Course(String course, String section, String crn, int credits) {
this.course = course;
this.section = section;
this.crn = crn;
this.credits = credits;
} // end Course() initalizing
// muatator methods
public void setCampus(String cmp) {
this.campus = cmp;
}// end setCampus()
public void setCourse(String crse) {
this.course = crse;
}// end setCourse()
public void setSection(String sect) {
this.section = sect;
} // end setSection()
public void setCRN(String crn) {
this.crn = crn;
} // end setCRN()
public void setCredits(int cr) {
this.credits = cr;
} // end setCredits()
public void setTime(String tm) {
this.time = tm;
}// end setTime()
public void setDays(String days) {
this.days = days;
}// end setDays()
// accessor methods
public String getCampus() {
return campus;
} // end getCampus()
public String getCourse() {
return course;
} // end Course()
public String getSection() {
return section;
} // end getSection()
public String getCRN() {
return crn;
} // end getCRN()
public int getCredits() {
return credits;
} // end getCredits()
public String getTime() {
return time;
} // end getTime()
public String getDays() {
return days;
} // end getDays()
// method to compare by CRN using the String class compareTo()
public int compareTo(Course other) {
return this.crn.compareTo(other.getCRN());
} // end compareTO()
// method to return properties as a string
public String toString() {
return campus + " "
+ course + " "
+ section + " "
+ crn + " "
+ credits + " "
+ time + " "
+ days;
} // end toString()
// method to return properties as a CSV string on one line
//public String toCSVString(Course c){
public String toCSVString (Course c){
String record = campus + ","
+ course + ","
+ section + ","
+ crn + ","
+ credits + ","
+ time + ","
+ days + "\n";
return record;
} //end toCSVString()
}// end class Course
You have:
outfile.write(courseArray.toCSVString(courseArray[i]));
You mean:
outfile.write(courseArray[i].toCSVString(courseArray[i]));
As toCSVString is a member of Course, not of Course[] (courseArray is a Course[] and you are attempting to call .toCSVString() on the array itself, which is not valid).
Also note that in this form, it is redundant to pass the Course as a parameter, as you are not using it and you also would want this instead of some other Course anyways. I recommend either ditching that parameter entirely (since it is unused):
public String toCSVString () { // <- c wasn't actually used
String record = campus + "," // <- and this. is implied here
+ course + ","
+ section + ","
+ crn + ","
+ credits + ","
+ time + ","
+ days + "\n";
return record;
}
And you simply call it as:
outfile.write(courseArray[i].toCSVString());
Or, if you prefer you can make the method static and use the parameter (although that does not get you any particular benefit in this situation):
public static String toCSVString (Course c) {
String record = c.campus + ","
+ c.course + ","
+ c.section + ","
+ c.crn + ","
+ c.credits + ","
+ c.time + ","
+ c.days + "\n";
return record;
}
If you choose the static approach then you call it as:
outfile.write(Course.toCSVString(courseArray[i]));
I am trying to write a simple template engine to parse if statements.
<{if $value == true}>
say hello
<{/if}>
I have written working code However, If I have multiple if statements in the file I am parsing then if grabs only the first and last if statement. For example.
<{if $value1 == true}>
say hello
<{/if}>
...
<{if $value2 == true}>
say hello
<{/if}>
...
The code parses and returns:
say hello
<{/if}>
...
<{if $value2 == true}>
say hello
Rather than just returning say hello.
Thanks for your help In advance the code is as follows:
public class Templates {
private static String escape(String value) {
return value.replaceAll("\\$", "\\\\\\$");
}
public static String load(String name) {
return load(name, null);
}
public static String load(String name, Map<String, String> parse) {
String page = new Resources().getTextResource("lib/tpl/" + name);
if (page == null) {
return "The template, " + name + " was NOT FOUND.";
}
if (parse != null) {
Iterator it = parse.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
value = escape(value); // Prevents java exception. Can't deal with $
page = page.replaceAll("\\<\\{\\$" + key + "\\}\\>", value);
}
Pattern ptrn = Pattern.compile("\\<\\{if \\$([a-z]+)\\s*(==|!=|eq|neq|or|and)\\s*(\\w+)\\}\\>(\\p{ASCII}+)\\<\\{/if\\}\\>");
Matcher mtch = ptrn.matcher(page);
System.out.println("\n\n\n");
while(mtch.find()) {
System.out.println("Key is: " + mtch.group(1));
//System.out.println("Key: " + dateMatcher.group(2));
System.out.println("Value is: " + mtch.group(3));
System.out.println("Data is: " + mtch.group(4));
if(parse.get(mtch.group(1)).equals(mtch.group(3))) {
System.out.println("\n\n\nREPLACE");
page = page.replaceAll(ptrn.pattern(), escape(mtch.group(4)));
} else {
//dateMatcher.appendReplacement(page, "");
System.out.println("\n\n\nREMOVE - " + ptrn.pattern());
page = page.replaceAll(ptrn.pattern(), "");
}
}
System.out.println("\n\n\n");
}
return page;
}
}
This might be due to greedy nature.
Try this,
(\\p{ASCII}+?) instead of (\\p{ASCII}+)