I need to write some information into the JSON file.
I have written the following function:
public String toJSON() {
StringBuffer sb = new StringBuffer();
sb.append("\"" + MyConstants.VEHICLE_LABEL + "\":");
sb.append("{");
sb.append("\"" + MyConstants.CAPACITY1_LABEL + "\": " + String.valueOf(this.getCapacity(0)) + ",");
sb.append("\"" + MyConstants.CAPACITY2_LABEL + "\": " + String.valueOf(this.getCapacity(1)) + ",");
sb.append("\"" + MyConstants.CAPACITY3_LABEL + "\": " + String.valueOf(this.getCapacity(2)));
sb.append("}");
return sb.toString();
}
However, I want to make this function more flexible. In particular, how should I change this code if the number of capacity units is not fixed (1, 2 or 3)?
I think that there should be a FOOR loop, however I am not sure how to implement it correctly.
Well you could do the append only if this.getCapacity(i) is not empty.
You could do something like this with a for loop
for(int i=0; i < max; i++) {
if(!StringUtils.isEmpty(String.valueOf(this.getCapacity(i)))){
sb.append("\"" + String.format(MyConstants.CAPACITY_LABEL, i) + "\": " + String.valueOf(this.getCapacity(i)) + ",");
}
}
where MyConstants.CAPACITY_LABEL is something like "capacity%d_label"
But, as azurefrog said, I would use a json parser to do this.
You can try the following class that follows the popular builder pattern:
public class JsonVehicleBuilder {
private StringBuilder builder;
/**
* Starts off the builder with the main label
*/
public JsonVehicleBuilder(String mainLabel) {
builder = new StringBuilder();
builder.append("\"").append(mainLabel).append("\":");
builder.append("{");
}
public JsonVehicleBuilder appendSimpleValue(String label, String value) {
builder.append("\"").append(label).append("\":").append(value).append(",");
return this;
}
/**
* Appends the closing bracket and outputs the final JSON
*/
public String build() {
builder.deleteCharAt(builder.lastIndexOf(",")); //remove last comma
builder.append("}");
return builder.toString();
}
}
And then in your main method you would call:
JsonVehicleBuilder jsonVehicleBuilder = new JsonVehicleBuilder(MyConstants.VEHICLE_LABEL);
jsonVehicleBuilder.appendSimpleValue(MyConstants.CAPACITY1_LABEL,String.valueOf(this.getCapacity(0)))
.appendSimpleValue(MyConstants.CAPACITY2_LABEL,String.valueOf(this.getCapacity(1)))
.appendSimpleValue(MyConstants.CAPACITY3_LABEL,String.valueOf(this.getCapacity(2)));
String json = jsonVehicleBuilder.build();
You can then keep chaining the appendSimpleValue method as long as you like.
Related
I have a method that returns a String and I would like to test if it works correctly. For that I have a test.txt-file that I read and compare to the return value of my method. If I print both Strings out they are exactly the same! Somehow assertEquals still fails.. What am I doing wrong here?
Method to test:
public String statement() {
String result = "Rental Record for " + getName() + "\n";
int frequentRenterPoints = 0;
for (Rental each : this.rentals) {
frequentRenterPoints += each.getFrequentRenterPoints();
// show figures for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ " (" + each.getMovie().getQuality() + ")"
+ ": "
+ String.valueOf(each.getCharge()) + "\n";
}
// add footer lines
result += "Amount owed is " + String.valueOf(getTotalCharge()) + "\n";
result += "You earned " + String.valueOf(frequentRenterPoints)
+ " frequent renter points";
return result;
}
Test:
#Test
public void statementReturnsCorrectlyFormattedString() throws IOException {
// given
customer = new Customer("ElonMusk");
Movie movieOne = new Movie("IronMan1", PriceCodes.REGULAR, Quality.HD);
Movie movieTwo = new Movie("AvengersEndGame", PriceCodes.NEW_RELEASE, Quality.FOUR_K);
Rental rentalOne = new Rental();
rentalOne.setMovie(movieOne);
rentalOne.setDaysRented(5);
Rental rentalTwo = new Rental();
rentalTwo.setMovie(movieTwo);
rentalTwo.setDaysRented(1);
List<Rental> rentalList = new LinkedList<Rental>();
rentalList.add(rentalOne);
rentalList.add(rentalTwo);
customer.setRentals(rentalList);
String expectedString = "";
try {
expectedString = readFile("test.txt");
System.out.println("expected: " + "\n" +expectedString);
} catch (IOException e) {
throw new IOException("Error reading statementTestFile!", e);
}
// when
String statement = customer.statement();
// then
System.out.println("statement: " + "\n" + statement);
System.out.println(expectedString.equals(statement));
assertEquals(expectedString, statement);
}
Output: expectedString
expected:
Rental Record for ElonMusk
IronMan1 (HD): 6.5
AvengersEndGame (FOUR_K): 5.0
Amount owed is 11.5
You earned 2 frequent renter points
Output: statement
statement:
Rental Record for ElonMusk
IronMan1 (HD): 6.5
AvengersEndGame (FOUR_K): 5.0
Amount owed is 11.5
You earned 2 frequent renter points
readFile:
private String readFile(String file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader (file));
String line = null;
StringBuilder stringBuilder = new StringBuilder();
String ls = "\n";
try {
while((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(ls);
}
return stringBuilder.toString();
} finally {
reader.close();
}
}
The problem is in the trailing newline you add when reading from a file. You could in trim the string, but what if there were some empty lines at the end of file you wanted to read?
So you can either introduce a 'first line' boolean like that:
boolean isFirstLine = true;
while((line = reader.readLine()) != null) {
if (!isFirstLine) {
stringBuilder.append(ls);
}
stringBuilder.append(line);
isFirstLine = false;
}
Or maybe leave the loop as-is and after it runs delete last character from the builder with:
if (stringBuilder.length() > 0) {
stringBuilder.deleteCharAt(stringBuilder.length() - 1); // or stringBuilder.lastIndexOf("\n");
}
Or do a substring.
Or maybe read the lines into a List collection like ArrayList and later do String.join("\n", linesCollection);.
So, I am working on a java project that is concerned with genetic algorithm.
I have a main method that calls a function (Let's call it function 1) that calculates through until the specified iterations. I wanted to run the main method 100 times and collect the data, so I decided to use FileWriter inside the function 1 that I am calling in my main method.
public static int Runcnt = 0;
static int o = 0;
public static File statText = new File("C:\\Users\\ShadyAF\\Desktop\\StatTest.txt");
public static void main(String [] args){
while(Runcnt <= 100)
{
final long startTime = System.nanoTime();
MainAlgorithm mA = new MainAlgorithm("config.xml");
mA.cMA();
final long duration = System.nanoTime() - startTime;
System.out.println(duration/1000000000 + " seconds");
o = 0;
}
The above snippet of code is the main that I'm trying to loop. (function 1)
System.out.println("best = "+Main.indx+" = "+Main.val);
System.out.println("max_cnt: " + Main.max_cnt);
try {
FileOutputStream is = new FileOutputStream(Main.statText);
OutputStreamWriter osw = new OutputStreamWriter(is);
Writer w = new BufferedWriter(osw);
w.write("#" + Main.Runcnt + " Best#: " + Main.indx + " BestScore: " + Main.val + " MaxCnt: " + Main.max_cnt + "\n");
w.close();
} catch (IOException e) {
System.err.println("Problem writing to file.");
}
The above snippet of code is the mA.cMa() function that is inside the main loop.
I ran the code for a while and it appears that the program writes to the file only for the first loop and does not do anything for the rest of the looops.
Any help is much appreciated!
Edit: Why am I getting downvoted? At least leave a helpful comment :/
You should change your pattern from scratch... anyway you can try with something like this in your Main:
public static Path pathFile = Paths.get("C:\\Users\\..blah..\\stats.txt");
Then use in your loop
try {
String log = "#" + Main.Runcnt + " Best#: " + Main.indx + " BestScore: " + Main.val + " MaxCnt: " + Main.max_cnt + "\n";
Files.write(Main.pathFile, log.getBytes(), Files.exists(Main.pathFile) ? StandardOpenOption.APPEND : StandardOpenOption.CREATE);
} catch (IOException e) {
// exception handling
}
It is not so efficient, in particular in case of lot of records but whole code you wrote should need strong refactoring too :)
I want to create a run time String name in Java.
I tried something like using in JavaScript, but it is printing value like Status_Name_0 instead Open assigned to the String Status_Name_0
public static void GetPaymentStatusList(){
int i=0;
String Status_Name_0="Open";
String Status_ID_0="0";
String Status_Name_1="Approved";
String Status_ID_1="1";
String Status_Name_2="Denied";
String Status_ID_2="2";
for(i=0; i<3; i++){
Vars.PaymentStatusName_List.add("Status_Name_"+i);
Vars.PaymentStatusId_List.add("Status_ID_"+i);
}
}
but it is printing value like Status_Name_0 instead Open
Because that's what you added to the list...
add("Status_Name_"+i);
The way to get what you want would be a Map<String, String>
Map<String, String> map = new HashMap<>();
map.put("Status_Name_0", "Open");
// ...
for (int i=0;i<map.size();i++) {
String open = map.get("Status_Name_"+i);
}
How about you make some class instead, though?
public class PaymentStatus {
int id;
String name;
public PaymentStatus(int id, String name) {
this.id = id;
this.name = name;
}
#Override
public String toString() {
return String.format("%s[id: %d, name: %s]",
getClass().getSimpleName(), id, name);
}
}
And a List<PaymentStatus> would be preferred over appending integers to any variables.
public static List<PaymentStatus> getPaymentStatusList() {
List<PaymentStatus> list = new ArrayList<>();
paymentStatusList.add(new PaymentStatus(0, "Open"));
paymentStatusList.add(new PaymentStatus(1, "Approved"));
paymentStatusList.add(new PaymentStatus(2, "Denied"));
return list;
}
You're actually concatenating the string "Status_name_" with "0" which would result in "Status_name_0", a string, not a variable like Status_name_0. As far as I understand, you want the values of String_name_i (i= 0, 1, 2,....). To get that working, use String array.
String[] string_names = { "Open", "Approved", "Denied" };
int[] string_id = { 0, 1, 2 };
:You may not need a string_id array, as you can use the values of i in the for loop.
And add them in the list like:
Vars.PaymentStatusName_List.add(string_name[i]);
StringBuilder param = new StringBuilder();
param.append("shopid"
+ "=" + shopDetails.getShopId() + "&" + "username" + "=" + userDetail.getUserName() + "&" + "userid" + "=" + userDetail.getUserId() + "&");
for (int i = 0; i < brandList.size(); i++) {
param.append("brandId" + "[" + i + "]" + "=" + brandList.get(i).getBrandId()
+ "&" + "shortqua" + "[" + i + "]" + "=" + shortageStockList.get(i) + "&");
}
param.append("lattude" + "=" + String.valueOf(latitude) + "&" + "longitude" + "=" + String.valueOf(longitude));
I'm creating a game of hangman, and long story short, is there a shortcut of sorts to put this array of separate strings together into a string other than doing like below?
String after = under[0] + under[1] + under[2] + under[3] + under[4] + under[5] + under[6] + under[7] + under[8] + under[9] + under[10] + under[11] + under[12] + under[13] + under[14] + under[15] + under[16] + under[17] + under[18] + under[19] + under[20] + under[21];
You can do it with a loop, like this:
StringBuilder sb = new StringBuilder();
for (int i = 0 ; i != 22 ; i++) {
sb.append(under[i]);
}
String after = sb.toString();
You can also add strings to an initially empty string, but that's suboptimal, because all the intermediate strings get allocated and released in a loop.
Always use loop to perform repetitive operation like this.
Also, It is advised to use StringBuilder instead of String. String in JAVA is immutable.
StringBuilder sb = new StringBuilder();
int nCount = 22;
for (int iCnt = 0 ; iCnt <= nCount ; iCnt++) {
sb.append(under[iCnt]);
}
String after = sb.toString();
try it:
String after = "";
for (int i=0; i<22; i++)
after += under[i];
This code is not shorter, but is less tedious:
StringBuilder afterBldr = new StringBuilder();
for (String underEl : under) {
afterBldr.append(underEl);
}
String after = afterBldr.toString();
Apache Joiner can be used here.
Joiner.on("").join(names)
If you have access to the Apache Commons library, use the join() method, it's the nicest solution:
String str = StringUtils.join(under, "");
I hava a List<String> that I need to serialize or make a String representation.
For example I have:
myList.add("Bob");
myList.add("account");
myList.add("userId");
The list can contain variable number of items and I need it to be serialized in this form:
\Bob\-\account\-\userId\
I can do a for loop like:
String ss;
for (String s: myList) {
s = "\\" + s + "\\";
ss = s + "-";
}
However there will be a "-" in the tail of the resulting String ss
Or is there a Google Guava function to do this already?
Using Guava:
String s = Joiner.on('-').join(Iterables.transform(list, new Function<String, String>() {
#Override
public String apply(String input) {
return "\\" + input + "\\";
}
});
The straight-forward way to solve this using Guava is the Joiner:
System.out.println("\\" + Joiner.on("\\-\\").join(myList) + "\\");
You can easily use Apaches Commons StringUtils:
String ss = "\\" + StringUtils.join(myList.iterator(), "\\-\\") + "\\";
Firstly, it is recommended to use StringBuilder during such concatenations.
Secondly, you can use Apache Common Lang's StringUtils.join()` method as follows to achieve the same:
ss = "\\" + StringUtils.join(myList.iterator(), "\\-\\") + "\\";
You can fix it by changing your loop like:
String ss = "";
for (String s: myList) {
s = "\\" + s + "\\";
if(ss.equals("")) {
ss = s;
}
else {
ss += " - " + s;
}
}
Perhaps the other solutions is an old fashioned for loop which is based on the List size().
The other thing I would do is use a StringBuffer as it is more efficient than concatenating Strings. Internally when you concatenate a String, the object is destroyed and recreated.
int myListSize = myList.size();
StringBuffer ss = new StringBuffer(4);
for (int i=0; i < myListSize; i++) {
ss.append("\\").append(myList.get(i)).append("\\");
if (i < myListSize - 1) {
ss.append("-");
}
}
Then to output from a StringBuffer:
ss.toString();
Personally I think these for loops (as above) end up being easier to read.
The simplest code for string joining that I know goes like this:
String sep = "", out = "";
for (String s : myList) {
out += sep + '\\' + s + '\\';
sep = "-";
}