I have this Java function that's supposed to convert the string s to title case. It should return a copy of s to the caller, leaving s preserved.
Currently, rv ends up as an empty string. Can anyone tell me why?
private static String titleCase(String s) {
String rv = new String();
StringTokenizer strtok = new StringTokenizer(s);
// handle the potential null error: (should really output a runtime warning here)
if(s == null) return null;
while(strtok.hasMoreTokens()) {
String word = strtok.nextToken();
String firstLetter = word.substring(0,1);
String restOfWord = word.substring(1);
rv.concat(firstLetter.toUpperCase() + restOfWord.toLowerCase());
}
return rv;
}
Strings being immutable in Java, once you have declared rv as "" (= new String()) it won't change unless you allocate a new String to it.
You can either replace the concat line by:
rv = rv.concat(firstLetter.toUpperCase() + restOfWord.toLowerCase());
Or better, use a StringBuilder instead of a String (not tested):
StringBuilder rv = new StringBuilder();
// [...]
rv.append(firstLetter.toUpperCase()).append(restOfWord.toLowerCase());
// [...]
return rv.toString();
I'd use WordUtils.capitalize or WordUtils.capitalizeFully.
Related
I want to skip printing ", " in last iteration.
I want output like name, name, name
Output now i am getting is name, name, name,
StringBuffer stringBuffer = new StringBuffer();
for(MovieModel.Cast cast : movieModelList.get(position).getCastList()){
stringBuffer.append(cast.getName() + ", ");
}
You can append the comma before you append the name. Like this:
StringBuffer stringBuffer = new StringBuffer();
for(MovieModel.Cast cast : movieModelList.get(position).getCastList()){
if (stringBuffer.length() != 0) {
stringBuffer.append(",");
}
stringBuffer.append(cast.getName());
}
It's easier to insert the delimiter first. But, append the delimiter from a variable:
StringBuffer stringBuffer = new StringBuffer();
String delim = "";
for(MovieModel.Cast cast : movieModelList.get(position).getCastList()){
stringBuffer.append(delim);
stringBuffer.append(cast.getName());
delim = ",";
}
In this way, you don't append the , before the first element, but do before the subsequent elements.
A couple of notes:
Don't concatenate strings to append them to the buffer. This defeats the point of the buffer (somewhat, not entirely). Append one part, then append the other.
You almost certainly want to use a StringBuilder instead of StringBuffer:
As of release JDK 5, [StringBuffer] has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.
Why reinvent the wheel? Use StringUtils.join method from Apache Commons. Or you can inspire (copy+modify) from its sourcecode commons-lang-sources
// copied from https://commons.apache.org/proper/commons-lang/apidocs/src-html/org/apache/commons/lang3/StringUtils.html
public static String join(final Iterator<?> iterator, final String separator) {
// handle null, zero and one elements before building a buffer
if (iterator == null) {
return null;
}
if (!iterator.hasNext()) {
return EMPTY;
}
final Object first = iterator.next();
if (!iterator.hasNext()) {
return Objects.toString(first, "");
}
// two or more elements
final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
if (first != null) {
buf.append(first);
}
while (iterator.hasNext()) {
if (separator != null) {
buf.append(separator);
}
final Object obj = iterator.next();
if (obj != null) {
buf.append(obj);
}
}
return buf.toString();
}
After the loop, just remove the trailing comma and space:
stringBuffer.delete(stringBuffer.length() - 2, stringBuffer.length());
Try
StringBuffer stringBuffer = new StringBuffer();
for(MovieModel.Cast cast : movieModelList.get(position).getCastList()){
stringBuffer.append(cast.getName());
stringBuffer.append(", ");
}
stringBuffer.delete(stringBuffer.length() - 2, stringBuffer.length());
Hello I have following method to display a promotion line when I comment a shoutbox:
public String getShoutboxUnderline(){
StringBuilder builder = new StringBuilder();
builder.append("watch");
builder.append("on");
builder.append("youtube");
builder.append(":");
builder.append("Mickey");
builder.append("en");
builder.append("de");
builder.append("stomende");
builder.append("drol");
return builder.toString();
}
But when I get it, I get watchonyoutube:mickeyendestomendedrol, which is without spaces. How do I get spaces in my Stringbuilder?
As of JDK 1.8, you can use a StringJoiner, which is more convenient in your case:
StringJoiner is used to construct a sequence of characters separated
by a delimiter and optionally starting with a supplied prefix and
ending with a supplied suffix.
StringJoiner joiner = new StringJoiner(" "); // Use 'space' as the delimiter
joiner.add("watch") // watch
.add("on") // watch on
.add("youtube") // watch on youtube
.add(":") // etc...
.add("Mickey")
.add("en")
.add("de")
.add("stomende")
.add("drol");
return joiner.toString();
This way, you will not need to add those spaces "manually".
Just invoke builder.append(" ") at the location of your preference.
E.g.
builder
.append("watch")
.append(" ")
.append("on")
...etc.
NB:
Using the fluent builder syntax here for convenience
You can also just append a space after each literal instead (save for the last one)
Cleaner way of doing it.
Create a class variable:
private static final String BLANK_SPACE=" ";
Now in you StringBuilder code ,append it where required:
StringBuilder builder = new StringBuilder();
builder.append("watch");
builder.append(BLANK_SPACE);
builder.append("on");
builder.append("youtube");
builder.append(":");
builder.append(BLANK_SPACE);
builder.append("Mickey");
builder.append("en");
builder.append("de");
builder.append(BLANK_SPACE);
builder.append("stomende");
builder.append("drol");
System.out.println(builder.toString());
A space is only a string containing the single character space.
So you can append it exactly as appending any other string.
StringBuilder builder = new StringBuilder();
builder.append("watch");
builder.append(" ");
builder.append("on");
builder.append(" ");
// and so on
Remember also that the append method returns the StringBuilder so it is possible to join appends one after the other as follow
StringBuilder builder = new StringBuilder();
builder.append("watch").append(" ");
builder.append("on").append(" ");
// and so on
You can use this, it's equivalent to using StringBuilder or StringJoiner, but smaller
public class StringUnifier {
String separator = "";
List<String> dataList = new ArrayList<>();
private String response = "";
StringUnifier(String separator) {
this.separator = separator;
}
StringUnifier add(String data) {
if (!data.isEmpty()) {
this.dataList.add(data);
}
return this;
}
#Override
public String toString() {
this.dataList.forEach(str -> {
this.response += (str + this.separator);
});
return this.response.substring(0, this.response.length() - this.separator.length());
}
}
MAIN
public class Main_Test {
public static void main(String[] args) {
StringUnifier stringUnifier = new StringUnifier(" ");
stringUnifier.add("columna1").add("columna2").add("columna3");
System.out.println(stringUnifier.toString());
}
}
RUN
output:
columna1 columna2 columna3
I have a string array variable which values changes continuously. Random arrays are generated from it. This is what i have:
String trans = Utility.GetColumnValue(testdata[k], "suggest_text_2");
The trans value changes continuously. How can i concatenate it with the previous values? How can i print every value of trans as it changes continuously? Do i need to use any buffer?
If you need the intermediate results, you will probably need something like this:
String yourOldString;
String freshString;
// other code which updates freshString
yourOldString = yourOldString + " " + freshString;
However if you do need to catch all updates but only print out the final result, use a StringBuilder:
private static final String WHITESPACE = " ";
String yourOldString;
String freshString;
StringBuilder builder = new StringBuilder();
builder.append(yourOldString);
// other code which updates freshString
builder.append(WHITESPACE);
builder.append(freshString);
// once everything is done:
String resultString = builder.toString();
String a = "foo";
String space = " ";
String b = "bar";
String c = a+space+b;
It's often best to use StringBuilder to concatenate strings:
String [] array { "fee", "fie", "foe", "fum" };
boolean firstTime = true;
StringBuilder sb = new StringBuilder(50);
for (String word : array) {
if (firstTime) {
firstTime = false;
} else {
sb.append(' ');
}
sb.append(word);
}
String finalResult = sb.toString();
System.out.println("string1 "+"string2");
Simply,
String trans = Utility.GetColumnValue(testdata[k], "suggest_text_2");
StringBuffer concat = new StringBuffer();
concat.append(test).append(" ");
Or,
StringBuffer concat = new StringBuffer();
concat.append(Utility.GetColumnValue(testdata[k], "suggest_text_2")).append(" ");
To concatenate/combine set of data.
for(String s: trans){
concat.append(s).append(" ");
}
String concatenation(like trans + " ") is slower than the StringBuffer append(). I strongly suggest you to use StringBuilder. Because when combinig String on the fly StringBuffer is created and then using toString() converts to String.
Here is nice blog post to read to learn about performance of these two.
I have a problem with reading from a text file to an arraylist. The problem is that i don't know how to read in multiple types, because in my arraylist there are Points, Strings, booleans, therefor linesplit doesn't work. I checked all the topics and didn't find a solution to this.
edit: Elrendezes class looks like
class Elrendezes {
protected Point Po;
protected String hely;
protected String foglalo;
protected boolean foglalt;
}
Here's how my file looks like:
java.awt.Point[x=16,y=13], 1, name1, false
And the method to read is
public static ArrayList<Elrendezes> readDataFromFile(){
ArrayList<Elrendezes> ElrList = new ArrayList<Elrendezes>();
FileInputStream fstream = null;
try
{
fstream = new FileInputStream("src/files/DataFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine = null ;
String tokens[] = strLine.split(", ");
while ((strLine = br.readLine()) != null) {
tokens = strLine.split(", ");
// THIS DOES NOT WORK: ElrList.add(new Elrendezes(tokens[0], tokens[1], tokens[2], tokens[3]));
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try { fstream.close(); } catch ( Exception ignore ) {}
}
return ElrList;
}
As you probably dont know regular expressions, I will use:
Get x and y:
int v1 = strLine.indexOf("x=");
int v2 = strLine.indexOf(",y=");
int v3 = strLine.indexOf("]") ;
string x = strLine.substring(v1 +2, v2);
string y = strLine.substring(v2 +3, v3);
Break point representation from the rest.
string secondpart = strLine.substring(v3+1);
Now break secondpart with only the coma as separator.
Convert string representation, using Integer.parseInt() and etc..
Construct your object back.
Note: written in a hurry, check if the indexes used for x, y and secondpart are correct.
I also assumed the input is correct.
I think you have to choose a char to split the String.
Cast the split string into boolean, integer etc.
Elrendezes(String[] s){
Point Po = s[0]; // dont know how to cast string to point, never done before
hely = s[1];
foglalo = s[2];
foglalt = Boolean.parseBoolean(s[3]);
}
I like to replace a certain set of characters of a string with a corresponding replacement character in an efficent way.
For example:
String sourceCharacters = "šđćčŠĐĆČžŽ";
String targetCharacters = "sdccSDCCzZ";
String result = replaceChars("Gračišće", sourceCharacters , targetCharacters );
Assert.equals(result,"Gracisce") == true;
Is there are more efficient way than to use the replaceAll method of the String class?
My first idea was:
final String s = "Gračišće";
String sourceCharacters = "šđćčŠĐĆČžŽ";
String targetCharacters = "sdccSDCCzZ";
// preparation
final char[] sourceString = s.toCharArray();
final char result[] = new char[sourceString.length];
final char[] targetCharactersArray = targetCharacters.toCharArray();
// main work
for(int i=0,l=sourceString.length;i<l;++i)
{
final int pos = sourceCharacters.indexOf(sourceString[i]);
result[i] = pos!=-1 ? targetCharactersArray[pos] : sourceString[i];
}
// result
String resultString = new String(result);
Any ideas?
Btw, the UTF-8 characters are causing the trouble, with US_ASCII it works fine.
You can make use of java.text.Normalizer and a shot of regex to get rid of the diacritics of which there exist much more than you have collected as far.
Here's an SSCCE, copy'n'paste'n'run it on Java 6:
package com.stackoverflow.q2653739;
import java.text.Normalizer;
import java.text.Normalizer.Form;
public class Test {
public static void main(String... args) {
System.out.println(removeDiacriticalMarks("Gračišće"));
}
public static String removeDiacriticalMarks(String string) {
return Normalizer.normalize(string, Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
}
}
This should yield
Gracisce
At least, it does here at Eclipse with console character encoding set to UTF-8 (Window > Preferences > General > Workspace > Text File Encoding). Ensure that the same is set in your environment as well.
As an alternative, maintain a Map<Character, Character>:
Map<Character, Character> charReplacementMap = new HashMap<Character, Character>();
charReplacementMap.put('š', 's');
charReplacementMap.put('đ', 'd');
// Put more here.
String originalString = "Gračišće";
StringBuilder builder = new StringBuilder();
for (char currentChar : originalString.toCharArray()) {
Character replacementChar = charReplacementMap.get(currentChar);
builder.append(replacementChar != null ? replacementChar : currentChar);
}
String newString = builder.toString();
I'd use the replace method in a simple loop.
String sourceCharacters = "šđćčŠĐĆČžŽ";
String targetCharacters = "sdccSDCCzZ";
String s = "Gračišće";
for (int i=0 ; i<sourceCharacters.length() ; i++)
s = s.replace(sourceCharacters.charAt[i], targetCharacters.charAt[i]);
System.out.println(s);