Java replace string with increasing number - java

I want to replace "a" of "abababababababab" with 001,002,003,004......
that is "001b002b003b004b005b....."
int n=1
String test="ababababab";
int lo=test.lastIndexOf("a");
while(n++<=lo) Abstract=Abstract.replaceFirst("a",change(n));
//change is another function to return a string "00"+n;
however this is poor efficiency,when the string is large enough,it will take minutes!
do you have a high efficiency way?
thanks very much!

Use a Matcher to find and replace the as:
public static void main(String[] args) {
Matcher m = Pattern.compile("a").matcher("abababababababab");
StringBuffer sb = new StringBuffer();
int i = 1;
while (m.find())
m.appendReplacement(sb, new DecimalFormat("000").format(i++));
m.appendTail(sb);
System.out.println(sb);
}
Outputs:
001b002b003b004b005b006b007b008b

Related

What is the fastest way to make substring by searching and deleting the old substring in java?

My business logic is quite weird, but in short, I will explain here.
I have to remove the first or last occurrence of a sub string, then repeat the process. I think below code is working fine till now. Now I want to know how to optimize it because it's not performing well for large input(string length of 10000) data.
int count =0;
while(s.contains(substr))
{
s= s.replaceFirst(substr,"");
// doSomeBusinessLogic(s);
count++;
}
return count;
examples
test 1
s = abababab
substr = ab
count = 4
test 2
s = aeerrb
substr = er
count =2
because after removing first er, the string becomes aerb,
so remove the er again. so count is 2.
Edited- as per the answer it looks like matcher is better to use, however, its not producing an excepted answer.
public class Solution {
static int maxMoves(String s, String substr) {
int count = 0;
StringBuffer buf = new StringBuffer();
Matcher m = Pattern.compile(substr).matcher(s);
while (m.find()) {
m.appendReplacement(buf, "");
count++;
}
m.appendTail(buf);
// System.out.println(buf.toString());
return count;
}
public static void main(String[] args) {
System.out.println("Max Moves"+ Solution.maxMoves("aeerrb","er"));
}
}
Disclaimer: The code in this answer will not handle test 2 given in the example that was later added to the question.
With your code, inserting print statements, you get:
String s = "This is a test";
String substr = " ";
int count = 0;
while (s.contains(substr)) {
s = s.replaceFirst(substr, "");
System.out.println("doSomeBusinessLogic(\"" + s + "\")");
count++;
}
System.out.println("count = " + count);
Output
doSomeBusinessLogic("Thisis a test")
doSomeBusinessLogic("Thisisa test")
doSomeBusinessLogic("Thisisatest")
count = 3
First, the parameter to replaceFirst() is a regex, so you need to escape the parameter, so regex special characters like ., ?, *, [, {, ... are treated literally, not as regex patterns. To do that, call Pattern.quote().
Then, to improve the code, so you don't scan the text twice (contains() and replaceFirst()), and continue scanning from where you are, instead of from beginning, use a variant for the standard appendReplacement() loop:
String s = "This is a test";
String substr = " ";
int count = 0;
StringBuffer buf = new StringBuffer();
Matcher m = Pattern.compile(Pattern.quote(substr)).matcher(s);
while (m.find()) {
m.appendReplacement(buf, "");
String ss = buf + s.substring(m.end());
System.out.println("doSomeBusinessLogic(\"" + ss + "\")");
count++;
}
// not needed here, but loop usually ends with: m.appendTail(buf);
System.out.println("count = " + count);
Output is the same as before.
For reference, here is a more normal appendReplacement loop, that replaces the spaces with the count value:
int count = 0;
StringBuffer buf = new StringBuffer();
Matcher m = Pattern.compile(" ").matcher("This is a test");
while (m.find()) {
m.appendReplacement(buf, String.valueOf(count));
count++;
}
m.appendTail(buf);
System.out.println(buf.toString()); // prints: This0is1a2test

String Regex for insert text based on searchstring

I have the following class.
public class TestStringRegex {
public static void main(String[] args) {
StringBuilder text = new StringBuilder("KALAKA");
String wordToFind = "KA";
Pattern word = Pattern.compile(wordToFind);
Matcher match = word.matcher(text);
while (match.find()) {
System.out.println(match.end());
text=text.insert(match.end(),"INSERT");
}
System.out.println(text);
}
Expecting output to be KAINSERTLAKAINSERT.
But getting KAINSERTLAKA.
Is matcher/insert works on the length of input text?How to get desired output.
If you want to do it using matcher use the overloaded method with int i.e. matcher.find(index). For some reason mathcher.find() is not working as given in docs. If you are curious you need to debug the code.
Just say like below
int end = 0;
while (match.find(end)) {
end = match.end();
System.out.println(end);
text=text.insert(end,"INSERT");
}
Better way of doing the same will be
public static void main(String[] args) {
System.out.println("KALAKA".replaceAll("KA", "$0INSERT"));
}
That's all the code you need to write.
Use matcher.find(int startIndex) instead of find(). And update startIndex after each match. Full code:
public static void main(String[] args) {
StringBuilder text = new StringBuilder("KALAKA");
String wordToFind = "KA";
Pattern word = Pattern.compile(wordToFind);
Matcher match = word.matcher(text);
int findIndex = 0;
while (match.find(findIndex)) {
int end = match.end();
findIndex = end;
text = text.insert(end, "INSERT");
}
System.out.println(text);
}
Each next find() starts at the end of previous match
This works fine..!!!
public static void main(String[] args) {
StringBuilder text = new StringBuilder("KALAKA");
String wordToFind = "KA";
Pattern word = Pattern.compile(wordToFind);
Matcher match = word.matcher(text);
int end = 0;
while (match.find(end)) {
end = match.end();
text=text.insert(match.end(),"INSERT");
}
System.out.println(text);
}

How can I split string using Regular Expression(Pattern)?

I want to split my String (e.g. "20150101") using Regular Expression.
For example I need these values: "2015","01","01"
String pattern = "(....)(..)(..)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(inputString);//inputString:"20150101"
Now you can use m.group(x) to get the parts of the string. For example:
m.group(1) is first four digit ("2015" in your question).
Bit hard to say without more details, but try:
(\d{4})(\d{2})(\d{2})
Your Matcher's three captured group references will then have the values you want.
Just combining the two answers both are valid
First
public static void main(String[] args) {
String input = "20150101";
String pattern = "(....)(..)(..)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(input);
m.find();
for(int i=1;i<=m.groupCount();i++){
String token = m.group( i );
System.out.println(token);
}
}
Second
public static void main(String[] args) {
String input = "20150101";
String pattern = "(\\d{4})(\\d{2})(\\d{2})";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(input);
m.find();
for(int i=1;i<=m.groupCount();i++){
String token = m.group( i );
System.out.println(token);
}
}
private static final Pattern DATE_PATTERN = Pattern.compile("^([\\d]{4})([\\d]{2})([\\d]{2})$");
public static Optional<String[]> split(String str) {
final Matcher matcher = DATE_PATTERN.matcher(str);
if (matcher.find()) {
final String[] array = new String[3];
array[0] = matcher.group(1);
array[1] = matcher.group(2);
array[2] = matcher.group(3);
return Optional.of(array);
}
return Optional.empty();
}

ReplaceFirst with Regular Expression

Let's say I have a String
String link = "www.thisisalink.com/tick1=#tick1#&tick2=#tick2#&tick3=#tick3#&tick4=#tick4#";
Then I can use
link = replaceFirst("(.+)=#\\1#", "");
To make it
link = "www.thisisalink.com/&tick2=#tick2#&tick3=#tick3#&tick4=#tick4#";
But I want to loop though the String, to get what has been replace and save it somewhere else, like a linked list or an array... result would be:
String[] result = ["tick1=#tick1#", "tick2=#tick2#", "tick3=#tick3#", "tick4=#tick4#"];
String link = "www.thisisalink.com/&&&";
But how can I do this? I tried looping with
while (link.matches("(.+)=#\\1#")){}
Which didn't work.
You can use Pattern Matcher classes to iterate over your string to find substrings that will match your regex. Then to replace founded substring you can use appednReplacement and appendTail. To get founded match you can use group() from Matcher instance.
Here is something similar to what you want
String link = "www.thisisalink.com/tick1=#tick1#&tick2=#tick2#&tick3=#tick3#&tick4=#tick4#";
StringBuffer sb = new StringBuffer();
Pattern p = Pattern.compile("(.+)=#\\1#");
Matcher m = p.matcher(link);
List<String> replaced = new ArrayList<>();
while (m.find()) {
m.appendReplacement(sb, "");
replaced.add(m.group());
}
m.appendTail(sb);
//to replace link with String stored in sb use link=sb.toString();
//otherwise link will be unchanged
System.out.println(sb);
System.out.println(replaced);
output:
www.thisisalink.com/&&&
[tick1=#tick1#, tick2=#tick2#, tick3=#tick3#, tick4=#tick4#]
This produces the Strings you want:
public static void main(String[] args)
{
final String link = "www.thisisalink.com/tick1=#tick1#&tick2=#tick2#&tick3=#tick3#&tick4=#tick4#";
final int index = link.indexOf("/") + 1;
final String[] result = link.substring(index).split("&");
final String newLink = link.substring(0, index) + repeat("&", result.length -1);
System.out.println(newLink);
for(final String tick : result)
{
System.out.println(tick);
}
}
private static String repeat(final String toRepeat, final int repetitions)
{
final StringBuilder sb = new StringBuilder(repetitions);
for(int i = 0; i < repetitions; i++)
{
sb.append(toRepeat);
}
return sb.toString();
}
Produces:
www.thisisalink.com/&&&
tick1=#tick1#
tick2=#tick2#
tick3=#tick3#
tick4=#tick4#

in matcher.replace method,how to limit replace times?

in matcher.replace method,only has:
replaceFirst() and replaceAll() two methods
i want limit replace 3 times,how to do?
example:
String content="aaaaaaaaaa";
i want to get result is: "bbbaaaaaaa"
my code:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class T1 {
public static void main(String[] args) {
String content="aaaaaaaaaa";
Pattern pattern = Pattern.compile("a");
Matcher m=pattern.matcher(content);
if(m.find()){
String result=m.replaceFirst("b");
System.out.println(result);
}
}
}
thanks :)
On appendReplacement/Tail
You'd have to use appendReplacement and appendTail explicitly. Unfortunately you have to use StringBuffer to do this. Here's a snippet (see also in ideone.com):
String content="aaaaaaaaaa";
Pattern pattern = Pattern.compile("a");
Matcher m = pattern.matcher(content);
StringBuffer sb = new StringBuffer();
final int N = 3;
for (int i = 0; i < N; i++) {
if (m.find()) {
m.appendReplacement(sb, "b");
} else {
break;
}
}
m.appendTail(sb);
System.out.println(sb); // bbbaaaaaaa
See also
StringBuilder and StringBuffer in Java
StringBuffer is synchronized and therefore slower than StringBuilder
BugID 5066679: Matcher should make more use of Appendable
If granted, this request for enhancement would allow Matcher to append to any Appendable
Another example: N times uppercase replacement
Here's another example that shows how appendReplacement/Tail can give you more control over replacement than replaceFirst/replaceAll:
// replaces up to N times with uppercase of matched text
static String replaceUppercase(int N, Matcher m) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < N; i++) {
if (m.find()) {
m.appendReplacement(
sb,
Matcher.quoteReplacement(m.group().toUpperCase())
);
} else {
break;
}
}
m.appendTail(sb);
return sb.toString();
}
Then we can have (see also on ideone.com):
Pattern p = Pattern.compile("<[^>]*>");
Matcher m = p.matcher("<a> b c <ddd> e <ff> g <$$$> i <jjj>");
System.out.println(replaceUppercase(4, m));
// <A> b c <DDD> e <FF> g <$$$> i <jjj>
// 1 2 3 4
The pattern <[^>]*> is just a simple example pattern that matches "<tags like this>".
Note that Matcher.quoteReplacement is necessary in this particular case, or else appending "<$$$>" as replacement would trigger IllegalArgumentException about an illegal group reference (because $ unescaped in replacement string is a backreference sigil).
On replaceFirst and replaceAll
Attached is the java.util.regex.Matcher code for replaceFirst and replaceAll (version 1.64 06/04/07). Note that it's done using essentially the same appendReplacement/Tail logic:
// Excerpt from #(#)Matcher.java 1.64 06/04/07
public String replaceFirst(String replacement) {
if (replacement == null)
throw new NullPointerException("replacement");
StringBuffer sb = new StringBuffer();
reset(); // !!!!
if (find())
appendReplacement(sb, replacement);
appendTail(sb);
return sb.toString();
}
public String replaceAll(String replacement) {
reset(); // !!!!
boolean result = find();
if (result) {
StringBuffer sb = new StringBuffer();
do {
appendReplacement(sb, replacement);
result = find();
} while (result);
appendTail(sb);
return sb.toString();
}
return text.toString();
}
Note that the Matcher is reset() prior to any replaceFirst/All. Thus, simply calling replaceFirst 3 times would always get you the same result (see also on ideone.com):
String content="aaaaaaaaaa";
Pattern pattern = Pattern.compile("a");
Matcher m = pattern.matcher(content);
String result;
result = m.replaceFirst("b"); // once!
result = m.replaceFirst("b"); // twice!
result = m.replaceFirst("b"); // one more for "good" measure!
System.out.println(result);
// baaaaaaaaa
// i.e. THIS DOES NOT WORK!!!
See also
java.util.regex.Matcher source code, OpenJDK version
i think use StringUtils
code
org.apache.commons.lang3.StringUtils.replace(content,"a","b",3);

Categories