This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 5 years ago.
I need to make a simple code, which get a string, and an array of String, and replace the ? signs with each element of array.
Here is the test case in junit:
#Test
public void QueryFitterTest() {
ArrayList<String> args=new ArrayList<String>();
args.add("Bad code");
args.add("The code is buggy");
String res = QueryMaker.queryFitter("insert into vulnerability (name,descirption) values(?,?)",args);
String correctQuery="insert into vulnerability (name,descirption) values(Bad code,The code is buggy)";
assertEquals(correctQuery, res);
}
and here is the code:
public static String queryFitter(String query, ArrayList<String> args){
String[] colapsedQuery = query.split("");
int parmNum=0;
for(int i=0;i<colapsedQuery.length;i++){
if(colapsedQuery[i]=="?"){
colapsedQuery[i]=args.get(parmNum);
parmNum++;
}
}
query=concatenator(colapsedQuery);
return query;
}
public static String concatenator(String[] colapsedQuery){
String delimiter = "";
String result = String.join(delimiter, colapsedQuery);
System.out.println("query is: "+result);
return result;
}
The code is working fine but
I don't like my approach, is there an easier way to do it?
There are 2 issues:
1- My code cannot pass the test, it returns the query without any
change.
query is: insert into vulnerability (name,descirption) values(?,?)
2-
I don't like my approach, is there an easier way to do it?
Well, the good news is that your JUnit test discovered a bug in your program. The other good news is that the answer to both of your questions is the same. Just fix your code in the method queryFitter.
Try the following code:
public static String queryFitter(String query, ArrayList<String> args){
for(int i=0;i<args.size();i++){
query = query.replaceFirst("\\?",args.get(i));
}
return query;
}
Almost forgot to tell you. You don't need concatenator method either.
Related
This question already has answers here:
Try Catch Performance Java
(4 answers)
Closed 3 months ago.
First of all, I want to describe that there are more than five thousand records. Please let me know the best method for best performance from the following:
String hmVALUE = "";
try
{
hmVALUE = hashmapRECORDS.get(key).toString();
}
catch(Exception ex)
{
hmVALUE = "";
}
// Second method:
String hmVALUE = "";
if(Module.hmQUEUED_REQUESTS.containsKey(key))
{
hmVALUE = hashmapRECORDS.get(key).toString();
}
else
{
hmVALUE = "";
}
I am using try-catch and want to know which method is best.
Neither is ideal. Better to call get() and check if the result is null:
String hmVALUE = "";
Object value = hashmapRECORDS.get(key);
if (value != null) {
hmVALUE = value.toString();
}
Generally speaking, exceptions are much heavier operations for Java to generate (they need to collect stack traces, etc...) so in this specific case, I would say that if-statement is much better than try-catch.
However, for the question in general, those are completely different mechanisms - the 1st one should handle an unexpected error, while the other one is flow control.
Moreover, you can use the short condition ? if true : if false syntax and have the entire code like this:
String hmVALUE = Module.hmQUEUED_REQUESTS.containsKey(key) ? hashmapRECORDS.get(key).toString() : ""
And more specifically in your case, you can just use the getOrDefault() method:
String hmVALUE = hashmapRECORDS.getOrDefault(key, "");
This question already has answers here:
Multiple if statements with single else statement
(2 answers)
Closed 6 years ago.
I want to fill the acts array with values of some enum. While iterating I want to input commands from console, but my if statements don't find any match and I always get the output "Incorrect".
My code:
Action[] acts = new Action[n];
for(int i = 0; i < n; i++) {
System.out.println("Enter act: ");
Scanner in1 = new Scanner(System.in);
String s = in1.next();
acts[i] = new Action();
if (s.equals("rotate_forw"))
acts[i].type = ActionType.RotF;
if (s.equals("rotate_back"))
acts[i].type = ActionType.RotB;
if (s.equals("shift_forw"))
acts[i].type = ActionType.ShiftF;
if (s.equals("shift_back"))
acts[i].type = ActionType.ShiftB;
else
System.out.println("Incorrect");
}
Your else clause applies only to the last if statement, so you get the "Incorrect" output whenever s.equals("shift_back") is false.
Your statements should be replaced with a single if-else-if...-else statement, so that "Incorrect" is only printed if all the conditions are false :
Action[] acts = new Action[n];
for(int i = 0; i < n; i++) {
if (s.equals("rotate_forw"))
acts[i].type = ActionType.RotF;
else if (s.equals("rotate_back"))
acts[i].type = ActionType.RotB;
else if (s.equals("shift_forw"))
acts[i].type = ActionType.ShiftF;
else if (s.equals("shift_back"))
acts[i].type = ActionType.ShiftB;
else
System.out.println("Incorrect");
}
You should also consider what you want to assign to acts[i].type when the input is incorrect. Perhaps you should throw an exception in this case.
While #Eran's answer is correct, I'd like to suggest a different approach that encapsulates the enum with the translation from the external coding. Consider this:
public class EnumDemo
{
public static enum ActionType
{
Incorrect(""),
RotF("rotate_forw"),
RotB("rotate_back"),
ShiftF("shift_forw"),
ShiftB("shift_back");
private String code;
private ActionType(String code)
{
this.code = code;
}
public static ActionType fromString(String code)
{
return Arrays.stream(ActionType.values())
.filter(v->v.code.equals(code))
.findFirst()
.orElse(ActionType.Incorrect);
}
}
public static void main(String[] args)
{
String[] testData = {
"rotate_forw",
"rotate_back",
"shift_forw",
"shift_back",
"junk",
null };
Arrays.stream(testData)
.forEach(t->System.out.printf("\"%s\" -> ActionType.%s\n", t, ActionType.fromString(t)));
}
}
This uses the fact that enum constants can have associated data. I've added an instance variable code to hold the external encoding of each enum value. Then I added a static fromString(String code) method to the enum that looks up the provided code in the list of values. For 4 possibilities a simple linear search, equivalent to your if-then-else cascade, works fine. If there were dozens or more I'd set up a Map<String,ActionType> to handle the conversion.
The search using streams bears some explanation.
First create a Stream of enum values
Filter it to contain only enum values whose code matches the desired code (there should be only one)
Pick off the first entry, which comes back in a Optional. If nothing was found (i.e. the code is invalid) the Optional will be empty.
Use the orElse method to return the value if it exists or ActionType.Incorrect if not.
At first glance this might look inefficient since one expects that the filter() predicate has to scan the entire stream even if the desired element occurs early. This is a really nifty feature of Streams -- all intermediate streams are "lazy", so the filter won't iterate over the entire list if it finds the desired entry early. See this question for details.
Output:
"rotate_forw" -> ActionType.RotF
"rotate_back" -> ActionType.RotB
"shift_forw" -> ActionType.ShiftF
"shift_back" -> ActionType.ShiftB
"junk" -> ActionType.Incorrect
"null" -> ActionType.Incorrect
The last testcase shows the code is null-safe.
The biggest advantage is that the mapping is in the same place as the enum itself, so you won't have to hunt for the code when you add or remove an enum value. Also you can't forget to define the mapping since it's required by the enum's constructor.
This question already has answers here:
toUpperCase in Java does not work [duplicate]
(5 answers)
Closed 6 years ago.
I use Eclipse IDE to program for java.
I wrote a class to show whether a name is in a CuncurrentHashMap, my IDE does not show me any error, yet whenever I run my program, I do not get my desired output. My desired output is to have the queries name "Jerry" capitalised. I am only learning the advance principles in java, I am familiar with the basic concepts but I am open to any correction or criticism you have towards my coding style below.
package learnJavaPackages;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
public class AddEmployee {
private String newEmployeeName;
private int empID=0;
ConcurrentHashMap<String, String> hashHandler = new ConcurrentHashMap<String, String>();
Scanner inputHere = new Scanner(System.in);
public void AddNewEmployee(){
System.out.print("Enter a new employee here: " );
newEmployeeName = inputHere.nextLine();
empID++;
String empIDstring = Integer.toString(empID);
newEmployeeName = newEmployeeName+empIDstring;
hashHandler.put(newEmployeeName, empIDstring);
}
public void showAddStatus(){
System.out.println(newEmployeeName +", has been added to the company");
}
public void showIsEmployeeIn(String isEmployee) {
isEmployee.toUpperCase();
if(hashHandler.containsKey(isEmployee)){
System.out.println(isEmployee +" is in the Company.");
}
else{
System.out.println(isEmployee +" is not in the company");
}
}
}
main method:
AddEmployee addEmpRef = new AddEmployee();
addEmpRef.AddNewEmployee();
addEmpRef.showAddStatus();
addEmpRef.showIsEmployeeIn("Jerry");
output:
Enter a new employee here: Isaac
Isaac1, has been added to the company
Jerry is not in the company
.toUpperCase() returns a brand new instance of String, which you don't assign to any variable. Just do:
isEmployee = isEmployee.toUpperCase();
String is immutable. Thus sEmployee.toUpperCase() does not change the sEmployee object. Instead it returns a new String. Use
sEmployee = sEmployee.toUpperCase();
Strings are immutable. As a result, all "mutating" methods return the updated String instead, and you need to pick that up.
isEmployee = isEmployee.toUpperCase();
This question already has answers here:
Modify a .txt file in Java
(12 answers)
Closed 8 years ago.
I need some help or code examples to update an existing line.
File contents:
Heinrich: 30
George: 2020
Fred: 9090129
Say if I wanted to update (write) George's value to say 300, how would I achieve this?
EDIT: Or would it be better off just using YAML?
Thanks.
Here is a way to do it, try it. In this example the file is C:/user.txt and i change the value of George by 1234
public class George {
private static List<String> lines;
public static void main (String [] args) throws IOException{
File f = new File("C:/user.txt");
lines = Files.readAllLines(f.toPath(),Charset.defaultCharset());
changeValueOf("Georges", 1234); // the name and the value you want to modify
Files.write(f.toPath(), changeValueOf("George", 1234), Charset.defaultCharset());
}
private static List<String> changeValueOf(String username, int newVal){
List<String> newLines = new ArrayList<String>();
for(String line: lines){
if(line.contains(username)){
String [] vals = line.split(": ");
newLines.add(vals[0]+": "+String.valueOf(newVal));
}else{
newLines.add(line);
}
}
return newLines;
}
}
This is a working solution, but i think there is some other way more efficient.
This question already has answers here:
Resize an Array while keeping current elements in Java?
(12 answers)
Closed 9 years ago.
I'd like to know if I can re-dimension an array as long as I want. I tried to do it and it seems there aren't any problems. I created an array with these steps
//step 1
String parole[];
//step 1
parole = new String[1];
parole[0] = "ciao";
//step 1
parole = new String[2];
parole[1] = "buongiorno";
I ask this beacuse there something in my mind that tells me that i can't do it. Maybe i read something somewhere someplace...
Of course you can create a new array object and assign it to an array reference.
But if you expected that parole[0] would still have "ciao" in it after your last step, you're wrong.
Yes you can, but you need to copy the first array into a new one.
Check this sample code:
public class ArrayCp {
public static void main(String[] args)
{
String[] primoArray = new String[1];
primoArray[0] = "Ciao";
// Copio il primo array nel secondo cambiandone la dimensione (secondo parametro)
String [] secondoArray = Arrays.copyOf(primoArray, 2);
secondoArray[1] = "Buona Sera";
for(String s : secondoArray) {
System.out.println("Elemento: " + s );
}
}
}
However is better going with an ArrayList:
ArrayList<String> theArr = new ArrayList<String>();
theArr.add("Ciao");
theArr.add("Buona Sera");
theArr.add("Buona Notte");
and get back to a simple array with
String [] resArray = theArr.toArray(new String[theArr.size()]);
Making a "new String[]" is just that, making a NEW string array. This means that any data you previously had in the reference is overwritten by the "new" object. (If you had other references to the string[] it wouldn't be lost however)
So, in short, no, you cannot "re-dimension" an array.
In your case, it is probably best to use an ArrayList, which provides for dynamic resizing (and is much easier to work with).
I agree with #BigMike
You should try ArrayList because it has built in methods for capacity which is far better than we doing it manually.
It does the work in amortized time which will be hard for us to achieve.
Refer this for more details.