How to improve the performance of below code ,Can you please provide any hints to improve the code performance is it correct way to use CopyOnWriteList .Is there any chance below code could cause memory leaks.
code:
public static List<TestVO> description(final TestVO desc) {
List<TestVO> descList = new CopyOnWriteArrayList<TestVO>();
final StringBuilder builder = new StringBuilder();
String add = "";
TestVO desc =null;
for (int i = 0; i < 2; i++) {
desc = new TestVO();
for (String key : audit.getLog().keySet()) {
if (!key.equals("hello")) {
builder.append(key + "=" + audit.getLog().get(key)
+ add);
add = ", ";
audit.getLog().remove(key);
} else {
desc.setDesc(key + " = "
+ audit.getLog().get(key));
descList.add(desc);
audit.getLog().remove(key);
break;
}
}
}
desc.setDesc("Checks : " + builder.toString());
descList.add(desc);
return descList;
}
Calling from main method:
TestVO a1=new TestVO();
a1.getLog().put("1", new BigDecimal(12));
a1.getLog().put("2", new BigDecimal(22));
a1.getLog().put("3", new BigDecimal(32));
a1.getLog().put("4", new BigDecimal(42));
a1.getLog().put("Hello", new BigDecimal(90));
description(a1);
TestVO has 2 methods one is log its type is HashMap and other one is desc its type is string.
Performance Tips for That Particular Code
Lose the seemingly useless first loop.
Use StringBuilder the way it's meant to be:
builder.append(key + "=" + audit.getLog().get(key) + add);
Should really be:
builder.append(key).append("=").append(audit.getLog().get(key)).append(add);
Do you really need a descList as a List and not a Set?
You don't need a CopyOnWriteArrayList here anyways. Or at Least we can't know if you need one from this code.
General Tips for That Particular Code
It's very unclear what that does, it looks like a made up and contrived example. Is it one?
Your code seems to make multiple things at once. Maybe it's good for performance, but maybe that also gives it a pretty weird design.
The way you change your add variable seems rather odd and it looks like you'd be better off building a collection and then generating the strings you need.
auditDesc is undeclared, so you probably didn't give us the correct code.
you say calling from main method, but we don't see any calls to description() (Found it, wasn't visible as it was outside of the code block.)
We have no clue what it's supposed to do, so I can't really be of more help until your provide a more complete code sample.
Related
At work, we have to generate a report for our client that changes its parameters several times during the week.
This report is generated from a single table on our database.
For example, imagine a table that has 100 columns and I have to generate a report with only 5 columns today, but tomorrow I have to generate with 95 of them.
With this in mind, I created a TO class with all the columns of the specified table and my query returns all columns (SELECT * FROM TABLE).
What I'm trying to create is a dynamic form to generate the report.
I first thought on create a simple frame with a list of the columns listed as check boxes and the user would select the columns that he wants (of course with a button to Select All and another to Deselect All).
As all of the columns have the same name as the attributes of the TO class, I developed the following code (I have Google this):
Class c = Test.class;
for(int i = 0; i < listOfAttributes.length; i++)
{
auxText += String.valueOf( c.getMethod( "get" + listOfAttributes[i]).invoke( this, null ) );
}
Is this the better way to do what I need to?
Thanks in advance.
Obs.: the getters of the TO class have the pattern "getAttribute_Name".
Note: This question is different from the one where the user is asking HOW to invoke some method given a certain name. I know how to do that. What I'm asking is if this is the better way to solve the problem I described.
My Java is a little more limited, but I believe that's about as good as you're going to get using reflection.
Class<?> c = Test.class;
for (String attribute : listOfAttributes) {
auxText += String.valueOf(c.getMethod("get" + attribute).invoke(this, null));
}
But since this sounds like it's from potentially untrusted data, I would advise using a HashMap in this case, with each method explicitly referenced. First of all, it explicitly states what methods can be dynamically called. Second, it's more type safe, and compile-time errors are way better than runtime errors. Third, it is likely faster, since it avoids reflection altogether. Something to the effect of this:
private static final HashMap<String, Supplier<Object>> methods = new HashMap<>();
// Initialize all the methods.
static {
methods.set("Foo", Test::getFoo);
methods.set("Bar", Test::getBar);
// etc.
}
private String invokeGetter(String name) {
if (methods.containsKey(name)) {
return String.valueOf(methods.get(name).get());
} else {
throw new NoSuchMethodException();
}
}
It might sound like a major DRY violation to do so, but the repetition at least makes sure you don't wind up with unrelated getters accidentally called.
Class c = Test.class;
for(int i = 0; i < listOfAttributes.length; i++)
{
auxText += String.valueOf( c.getMethod( "get" + listOfAttributes[i]).invoke( this, null ) );
}
You can do this somewhat more elegantly via Java Beans, the Introspector, and PropertyDescriptor, but it's a little more long-winded:
Map<String, Method> methods = new HashMap<>();
Class c = this.getClass(); // surely?
for (PropertyDescriptor pd : Introspector.getBeanInfo(c).getPropertyDescriptors())
{
map.put(pd.getName(), pd.getReadMethod();
}
//
for (int i = 0; i < listOfAttributes.length; i++)
{
Method m = methods.get(listOfAttributes[i]);
if (m == null)
continue;
auxText += String.valueOf(m.invoke(this, null));
}
I've got a database of playerdata that has some pre-existing fields from previous versions of the program. Example out-dated document:
{
"playername": "foo"
}
but a player document generated under the new version would look like this:
{
"playername": "bar",
"playercurrency": 20
}
the issue is that if I try to query playercurrency on foo I get a NullPointerException because playercurrency doesn't exist for foo. I want to add the playercurrency field to foo without disturbing any other data that could be stored in foo. I've tried some code using $exists Example:
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playername", "")));
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playercurrency", 20)));
My thought is that it updates only playercurrency because it doesn't exist and it would leave playername alone becuase it exists. I might be using exists horribly wrong, and if so please do let me know because this is one of my first MongoDB projects and I would like to learn as much as I possibly can.
Do you have to do this with java? Whenever I add a new field that I want to be required I just use the command line to migrate all existing documents. This will loop through all players that don't have a playercurrency and set it to 0 (change to whatever default you want):
db.players.find({playercurrency:null}).forEach(function(player) {
player.playercurrency = 0; // or whatever default value
db.players.save(player);
});
This will result in you having the following documents:
{
"playername" : "foo",
"playercurrency" : 0
}
{
"playername" : "bar",
"playercurrency" : 20
}
So I know that it is normally frowned upon on answering your own question, but nobody really posted what I ended up doing I would like to take this time to thank #Mark Watson for answering and ultimately guiding me to finding my answer.
Since checking if a certain field is null doesn't work in the MongoDB Java Driver I needed to find a different way to know when something is primed for an update. So after a little bit of research I stumbled upon this question which helped me come up with this code:
private static void updateValue(final String name, final Object defaultValue, final UUID key) {
if (!exists(name, key)) {
FindIterable iterable = players.find(new Document("_id", key));
iterable.forEach(new Block<Document>() {
#Override
public void apply(Document document) {
players.updateOne(new Document("_id", key), new Document("$set", new Document(name, defaultValue)));
}
});
}
}
private static boolean exists(String name, UUID key) {
Document query = new Document(name, new Document("$exists", true)).append("_id", key);
return players.count(query) == 1;
}
Obviously this is a little specialized to what I wanted to do, but with little revisions it can be easliy changed to work with anything you might need. Make sure to replace players with your Collection object.
I have the following code that defines a getParts method to find a given Part Name and Part Number in the system. Note that this code comes from our system's API, so if no one can help I'll just delete this question. I figured someone could potentially see a solution or help me along the way.
<%! private QueryResult getParts( String name, String number )
throws WTException, WTPropertyVetoException {
Class cname = wt.part.WTPart.class;
QuerySpec qs = new QuerySpec(cname);
QueryResult qr = null;
qs.appendWhere
(new SearchCondition(cname,
"master>name",
SearchCondition.EQUAL,
name,
false));
qs.appendAnd();
qs.appendWhere
(new SearchCondition(cname,
"master>number",
SearchCondition.EQUAL,
number,
false));
qr = PersistenceHelper.manager.find(qs);
System.out.println("...found: " + qr.size());
return qr;
}
%>
But I would like to allow the user more flexibility in finding these parts. So I set up conditional statements to check for a radio button. This allows them to search by part name and part number, find all, or search using a wildcard. However, I'm having trouble implementing the two latter options.
To attempt to accomplish the above, I have written the below code:
<%
String partName = request.getParameter("nameInput");
String partNumber = request.getParameter("numberInput");
String searchMethod = request.getParameter("selection");
//out.print(searchMethod);
QueryResult myResult = new QueryResult();
if(searchMethod.equals("search"))
myResult = getParts(partName, partNumber);
else if(searchMethod.equals("all"))
{
//Should I write a new function and do this?
//myResult = getAllParts();
//or is there a way I could use a for each loop to accomplish this?
}
//else if(searchMethod.equals("wildcard"))
//get parts matching %wildcard%
while(myResult.hasMoreElements())
{
out.print(myResult.nextElement().toString());
}
%>
Basically, it accepts user input and checks what type of search they would like to perform. Is there an easy way to pass all the values into the myResult object? And likewise for the wildcard search? Like I said before, it may be futile trying to help without access to the API, but hopefully it isn't.
Thanks!
You can (and should) reuse the function, but in order to do so, you will need a part name and number (as those are its input parameters). So for the multi-result options you will need to get a list/collection of part names+numbers and feed them individually to the function, then collect the result in the format that is most appropriate for your needs
I keep on copy-pasting the following in my programs. I'm wondering if anyone of you uses similar code, perhaps in a library to achieve the same.
#Override
public String toString() {
String ret = prefix;
boolean first = true;
for (Component child : children) {
if (!first) {
ret += " " + separator + " ";
} else {
first = false;
}
ret += child.getName();
}
return ret + postfix;
}
PS: One could use StringBuilder instead of String. Got that.
Apache commons provides a number of join methods in the StringUtils class.
This page also has a lot of interesting suggestions on the best way to implement such a method: http://snippets.dzone.com/posts/show/91
Nope. The only thing I can think of is it abstract that " " away into a final field in the toString() function. The reason that we don't have anything nicer is because the foreach construct doesn't care about the position, only that it will print sequentially.
That being said, avoid copy and paste at all costs. Make your own library if need be. Allow it to take a parameter of an interface which indicates if it is the first, and go from there.
User submits a CSV file which is consumed by a program. Values which are used throughout the program come from the CSV, natually if values are missed it is a problem. Below is my solution.
Ip on top
private List<String> currentFieldName = new ArrayList<String>();
As part of the method:
try {
setCurrentFieldName("Trim Space");
p.setTrimSpace(currentLineArray[dc.getTRIM_POSITION()].equals("yes") ? true : false);
setCurrentFieldName("Ignore Case");
p.setIgnoreCase(currentLineArray[dc.getIGNORE_CASE_POSITION()].equals("yes") ? true : false);
} catch (NullPointerException e) {
throw new InputSpreadsheetValueUnassignedException("\"Type\" field not set: " + currentFieldName);
}
And the method which keeps track of a current field being looked at:
private void setCurrentFieldName(String fieldName) {
currentFieldName.clear();
currentFieldName.add(fieldName);
}
The idea there is that if user fails to submit value and i will end up getting null, before throwing an exception, i will know what value was not assigned.
So, this being said, specific questions:
Is what i have shown below an acceptable solution?
Can you suggest something more elegant?
First thing that comes to my mind is that using an ArrayList to represent the name of a single field is superfluous.
Why not just define a private String currentFieldName; and inside your try { } do currentFieldName = "Trim Space" etc?
Also,
p.setTrimSpace(currentLineArray[index].equals("yes") ? true : false);
can just as well be expressed as
p.setTrimSpace(currentLineArray[index].equals("yes"));
If your code goes through many columns, you could definitely make it more elegant. If not, your time might be better spent on other parts of your project.
The answer to whether or not your solution is acceptable depends on the requirements, and a test suite would be the ideal party to provide the yes or the no.