Is there a method or way to read and keep reading chars from a string, putting them in a new string until there is a certain char.
Keep reading from < to > but no further.
Thankx
Of course. You will need:
the method String.charAt(int)
the + operator (or the method String.concat, or, if performance matters, the class StringBuilder)
the for statement
and perhaps an if-statement with a break statement
The statements and operators are explained in the Java Tutorial, and the method in the api javadoc.
(And no, I will not provide an implementation, since you would learn little by copying it)
You can actually write a utility that does that
public class StringUtil {
public static String copy(String str, char startChar, char endChar) {
int startPos = str.indexOf(startChar);
int endPos = str.lastIndexOf(endChar);
if (endPos < startPos) {
throw new RuntimeException("endPos < startPos");
}
char[] dest = new char[endPos - startPos + 1];
str.getChars(startPos, endPos, dest, 0);
return new String(dest);
}
};
PS Untested....
Alternatively, you can
String result = str.substring(startPos, endPos + 1); //If you want to include the ">" tag.
This may not be what you want but it will give you the desired string.
String desiredString="<Hello>".split("[<>]")[1];
Related
When working with a StringBuilder, I often append 2 char values to a StringBuilder using StringBuilder#append(char) twice, rather than StringBuilder#append(String).
I.e.:
StringBuilder builder = new StringBuilder();
builder.append(' ').append('t'); // would append(" t") work better here?
return builder.toString();
I would like to know:
Which approach is better performance-wise
Which approach is more common and why
I have already read through Using character instead of String for single-character values in StringBuffer append but it does not answer my question.
That question pertains to whether appending a single character (append('c')) is better than a single-character string (append("c")). I already understand why appending a single character is better than a single-character string, but I do not know whether appending a two-character string (append("ab")) is better than twice appending each character (append('a').append('b')).
In my testing, both of them seemed to take about the same time, however appending a string might be slightly slower (maybe 10 or so nanoseconds)
However, appending a string is much more popular as it's easier to use/understand.
This is really interesting to figure out this one.
As we all know the array is fast and internally String is using Character Array for storing the values.
internally both the method called the super.append(XXX) method ofAbstractStringBuilderclass.
if you see the code of append in AbstractStringBuilder for String and CharSeq
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
s = "null";
if ((start < 0) || (start > end) || (end > s.length()))
throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", s.length() "
+ s.length());
int len = end - start;
ensureCapacityInternal(count + len);
for (int i = start, j = count; i < end; i++, j++)
value[j] = s.charAt(i);
count += len;
return this;
}
These are the method internally called when you call append method.
Both the method calls the ensureCapacityInternal method to expand the array. So let's leave this method call as it is.
Now, the main difference comes in the next line of code.
The method with String args calls the getChars method. which internally call the System.arraycopy method, it's a native method and we can't predict the complexity of that method. it's based on the OS/JVM.
CharSeq method uses a for loop till the length of input charSequence.
for (int i = start, j = count; i < end; i++, j++)
value[j] = s.charAt(i);
i.e. it's completixity is depend on the length of input.
As I study, Other posts related to System.arraycopy method. They all say that it's effective than copying an array by a loop. even in an Effective Java Programing book.
So finally opinion, I would suggest that if the input is of small length then use the CharSequence only. Why waste the JVM for the small length String.
If you have long length string like a statement then go for a method with String args. Also, remember Space complexity increases in this case. i.e. String is immutable and you are creating more String every time in a pool. String.valueof(), (String)obj are examples.
Edited:
public AbstractStringBuilder append(char c) { ensureCapacityInternal(count + 1); value[count++] = c; return this; }
This method used when the args is char.
And seems that. It's more fast then others.
Because of assignment at count++ index of char. This method only contain the system.arraycopy method, which is common in all other method for ensuringcapacity.
Hope this will help. :)
What is the C++ equivalent of the following java function?
public StringBuilder replace(int start,
int end,
String str)
https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html#replace(int,%20int,%20java.lang.String)
Here is the replace all function we are using,
string ReplaceAll(string original, string replaceThis, string replaceWith)
{
std::string::size_type pos = 0;
while((pos = original.find(replaceThis, pos)) != std::string::npos)
{
original.replace(pos, (replaceThis.length()), replaceWith);
pos += replaceWith.length();
}
return original;
}
You can also refer the following link for better understanding.
REPLACE IN C++
C++'s string::replace is pretty similar to what you're looking for. However, instead of finding the range you want to replace with the left and right integer indexes, you pass in string iterators.
Basically given an int, I need to generate a String with the same length containing only the specified character. Related question here, but it relates to C# and it does matter what's in the String.
This question, and my answer to it are why I am asking this one. I'm not sure what's the best way to go about it performance wise.
Example
Method signature:
String getPattern(int length, char character);
Usage:
//returns "zzzzzz"
getPattern(6, 'z');
What I've tried
String getPattern(int length, char character) {
String result = "";
for (int i = 0; i < length; i++) {
result += character;
}
return result;
}
Is this the best that I can do performance-wise?
You should use StringBuilder instead of concatenating chars this way. Use StringBuilder.append().
StringBuilder will give you better performance. The problem with concatenation the way you are doing is each time a new String (string is immutable) is created then the old string is copied, the new string is appended, and the old String is thrown away. It's a lot of extra work that over a period of type (like in a big for loop) will cause performance degradation.
StringUtils from commons-lang or Strings from guava are your friends. As already stated avoid String concatenations.
StringUtils.repeat("a", 3) // => "aaa"
Strings.repeat("hey", 3) // => "heyheyhey"
Use primitive char arrays & some standard util classes like Arrays
public class Test {
static String getPattern(int length, char character) {
char[] cArray = new char[length];
Arrays.fill(cArray, character);
// return Arrays.toString(cArray);
return new String(cArray);
}
static String buildPattern(int length, char character) {
StringBuilder sb= new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(character);
}
return sb.toString();
}
public static void main(String args[]){
long time = System.currentTimeMillis();
getPattern(10000000,'c');
time = System.currentTimeMillis() - time;
System.out.println(time); //prints 93
time = System.currentTimeMillis();
buildPattern(10000000,'c');
time = System.currentTimeMillis() - time;
System.out.println(time); //prints 188
}
}
EDIT Arrays.toString() gave lower performance since it eventually used a StringBuilder, but the new String did the magic.
Yikes, no.
A String is immutable in java; you can't change it. When you say:
result += character;
You're creating a new String every time.
You want to use a StringBuilder and append to it, then return a String with its toString() method.
I think it would be more efficient to do it like following,
String getPattern(int length, char character)
{
char[] list = new char[length];
for(int i =0;i<length;i++)
{
list[i] = character;
}
return new string(list);
}
Concatenating a String is never the most efficient, since String is immutable, for better performance you should use StringBuilder, and append()
String getPattern(int length, char character) {
StringBuilder sb= new StringBuilder(length)
for (int i = 0; i < length; i++) {
sb.append(character);
}
return sb.toString();
}
Performance-wise, I think you'd have better results creating a small String and concatenating (using StringBuilder of course) until you reach the request size: concatenating/appending "zzz" to "zzz" performs probably betters than concatenating 'z' three times (well, maybe not for such small numbers, but when you reach 100 or so chars, doing ten concatenations of 'z' followed by ten concatenations of "zzzzzzzzzz" is probably better than 100 concatenatinos of 'z').
Also, because you ask about GWT, results will vary a lot between DevMode (pure Java) and "production mode" (running in JS in the browser), and is likely to vary depending on the browser.
The only way to really know is to benchmark, everything else is pure speculation.
And possibly use deferred binding to use the most performing variant in each browser (that's exactly how StringBuilder is emulated in GWT).
How do I get up to the first n characters of a string in Java without doing a size check first (inline is acceptable) or risking an IndexOutOfBoundsException?
Here's a neat solution:
String upToNCharacters = s.substring(0, Math.min(s.length(), n));
Opinion: while this solution is "neat", I think it is actually less readable than a solution that uses if / else in the obvious way. If the reader hasn't seen this trick, he/she has to think harder to understand the code. IMO, the code's meaning is more obvious in the if / else version. For a cleaner / more readable solution, see #paxdiablo's answer.
Don't reinvent the wheel...:
org.apache.commons.lang.StringUtils.substring(String s, int start, int len)
Javadoc says:
StringUtils.substring(null, *, *) = null
StringUtils.substring("", * , *) = "";
StringUtils.substring("abc", 0, 2) = "ab"
StringUtils.substring("abc", 2, 0) = ""
StringUtils.substring("abc", 2, 4) = "c"
StringUtils.substring("abc", 4, 6) = ""
StringUtils.substring("abc", 2, 2) = ""
StringUtils.substring("abc", -2, -1) = "b"
StringUtils.substring("abc", -4, 2) = "ab"
Thus:
StringUtils.substring("abc", 0, 4) = "abc"
Apache Commons Lang has a StringUtils.left method for this.
String upToNCharacters = StringUtils.left(s, n);
String upToNCharacters = String.format("%."+ n +"s", str);
Awful if n is a variable (so you must construct the format string), but pretty clear if a constant:
String upToNCharacters = String.format("%.10s", str);
docs
There's a class of question on SO that sometimes make less than perfect sense, this one is perilously close :-)
Perhaps you could explain your aversion to using one of the two methods you ruled out.
If it's just because you don't want to pepper your code with if statements or exception catching code, one solution is to use a helper function that will take care of it for you, something like:
static String substring_safe (String s, int start, int len) { ... }
which will check lengths beforehand and act accordingly (either return smaller string or pad with spaces).
Then you don't have to worry about it in your code at all, just call:
String s2 = substring_safe (s, 10, 7);
instead of:
String s2 = s.substring (10,7);
This would work in the case that you seem to be worried about (based on your comments to other answers), not breaking the flow of the code when doing lots of string building stuff.
Use the substring method, as follows:
int n = 8;
String s = "Hello, World!";
System.out.println(s.substring(0,n);
If n is greater than the length of the string, this will throw an exception, as one commenter has pointed out. one simple solution is to wrap all this in the condition if(s.length()<n) in your else clause, you can choose whether you just want to print/return the whole String or handle it another way.
ApacheCommons surprised me,
StringUtils.abbreviate(String str, int maxWidth) appends "..." there is no option to change postfix.
WordUtils.abbreviate(String str, int lower, int upper, String appendToEnd) looks up to next empty space.
I’m just going to leave this here:
public static String abbreviate(String s, int maxLength, String appendToEnd) {
String result = s;
appendToEnd = appendToEnd == null ? "" : appendToEnd;
if (maxLength >= appendToEnd.length()) {
if (s.length()>maxLength) {
result = s.substring(0, Math.min(s.length(), maxLength - appendToEnd.length())) + appendToEnd;
}
} else {
throw new StringIndexOutOfBoundsException("maxLength can not be smaller than appendToEnd parameter length.");
}
return result;
}
This question already has answers here:
Simple way to repeat a string
(32 answers)
Closed 4 years ago.
I did check the other questions; this question has its focus on solving this particular question the most efficient way.
Sometimes you want to create a new string with a specified length, and with a default character filling the entire string.
ie, it would be cool if you could do new String(10, '*') and create a new String from there, with a length of 10 characters all having a *.
Because such a constructor does not exist, and you cannot extend from String, you have either to create a wrapper class or a method to do this for you.
At this moment I am using this:
protected String getStringWithLengthAndFilledWithCharacter(int length, char charToFill) {
char[] array = new char[length];
int pos = 0;
while (pos < length) {
array[pos] = charToFill;
pos++;
}
return new String(array);
}
It still lacks any checking (ie, when length is 0 it will not work). I am constructing the array first because I believe it is faster than using string concatination or using a StringBuffer to do so.
Anyone else has a better sollution?
Apache Commons Lang (probably useful enough to be on the classpath of any non-trivial project) has StringUtils.repeat():
String filled = StringUtils.repeat("*", 10);
Easy!
Simply use the StringUtils class from apache commons lang project. You have a leftPad method:
StringUtils.leftPad("foobar", 10, '*'); // Returns "****foobar"
No need to do the loop, and using just standard Java library classes:
protected String getStringWithLengthAndFilledWithCharacter(int length, char charToFill) {
if (length > 0) {
char[] array = new char[length];
Arrays.fill(array, charToFill);
return new String(array);
}
return "";
}
As you can see, I also added suitable code for the length == 0 case.
Some possible solutions.
This creates a String with length-times '0' filled and replaces then the '0' with the charToFill (old school).
String s = String.format("%0" + length + "d", 0).replace('0', charToFill);
This creates a List containing length-times Strings with charToFill and then joining the List into a String.
String s = String.join("", Collections.nCopies(length, String.valueOf(charToFill)));
This creates a unlimited java8 Stream with Strings with charToFill, limits the output to length and collects the results with a String joiner (new school).
String s = Stream.generate(() -> String.valueOf(charToFill)).limit(length).collect(Collectors.joining());
In Java 11, you have repeat:
String s = " ";
s = s.repeat(1);
(Although at the time of writing still subject to change)
char[] chars = new char[10];
Arrays.fill(chars, '*');
String text = new String(chars);
To improve performance you could have a single predefined sting if you know the max length like:
String template = "####################################";
And then simply perform a substring once you know the length.
Solution using Google Guava
String filled = Strings.repeat("*", 10);
public static String fillString(int count,char c) {
StringBuilder sb = new StringBuilder( count );
for( int i=0; i<count; i++ ) {
sb.append( c );
}
return sb.toString();
}
What is wrong?
using Dollar is simple:
String filled = $("=").repeat(10).toString(); // produces "=========="
Solution using Google Guava, since I prefer it to Apache Commons-Lang:
/**
* Returns a String with exactly the given length composed entirely of
* the given character.
* #param length the length of the returned string
* #param c the character to fill the String with
*/
public static String stringOfLength(final int length, final char c)
{
return Strings.padEnd("", length, c);
}
The above is fine. Do you mind if I ask you a question - Is this causing you a problem? It seams to me you are optimizing before you know if you need to.
Now for my over engineered solution. In many (thou not all) cases you can use CharSequence instead of a String.
public class OneCharSequence implements CharSequence {
private final char value;
private final int length;
public OneCharSequence(final char value, final int length) {
this.value = value;
this.length = length;
}
public char charAt(int index) {
if(index < length) return value;
throw new IndexOutOfBoundsException();
}
public int length() {
return length;
}
public CharSequence subSequence(int start, int end) {
return new OneCharSequence(value, (end-start));
}
public String toString() {
char[] array = new char[length];
Arrays.fill(array, value);
return new String(array);
}
}
One extra note: it seems that all public ways of creating a new String instance involves necessarily the copy of whatever buffer you are working with, be it a char[], a StringBuffer or a StringBuilder. From the String javadoc (and is repeated in the respective toString methods from the other classes):
The contents of the character array are copied; subsequent modification of
the character array does not affect
the newly created string.
So you'll end up having a possibly big memory copy operation after the "fast filling" of the array. The only solution that may avoid this issue is the one from #mlk, if you can manage working directly with the proposed CharSequence implementation (what may be the case).
PS: I would post this as a comment but I don't have enough reputation to do that yet.
Try this Using the substring(int start, int end); method
String myLongString = "abcdefghij";
if (myLongString .length() >= 10)
String shortStr = myLongString.substring(0, 5)+ "...";
this will return abcde.
Mi solution :
pw = "1321";
if (pw.length() < 16){
for(int x = pw.length() ; x < 16 ; x++){
pw += "*";
}
}
The output :
1321************
Try this jobber
String stringy =null;
byte[] buffer = new byte[100000];
for (int i = 0; i < buffer.length; i++) {
buffer[i] =0;
}
stringy =StringUtils.toAsciiString(buffer);