public boolean frontAgain(String str)
{
int len = str.length();
if(len >= 2)
return str.substring(0, 2).equals(str.substring(len-2, len));
else
return false;
}
Can someone please explain why the second substring statement using a word example and a step by step analysis. The program checks if first two letters match the last two letters. for example the word was edited.
str.substring(len-2, len) asks for the last two letters of a string.
To get the last two letters, you need the beginning value of the substring to be the length (5) minus 2 characters, which gives you 3. This is because indexes in Java start at 0. For example, the positions for the characters in the string "horse" are 01234 (i.e. "h" is at index 0, "o" is at index 1 etc.), and the length is 5.
The second parameter of String.subString is for the ending index, which is exclusive. This means the first character position that is not part of the substring you want. In this case, it would be the length because that is 1 character higher than the end of the string.
If you put all that together, you get the following:
String str = "horse"
int length = str.length() // 5
String lastTwoChars = str.substring(length-2, length); // from position 3 to 5
System.out.println(lastTwoChars); // would show you "se"
The documentation for String.substring.
Related
hey I need a regex that removes the leadings zeros.
right now I am using this code . it does work it just doesn't keep the negative symbol.
String regex = "^+(?!$)";
String numbers = txaTexte.getText().replaceAll(regex, ")
after that I split numbers so it puts the numbers in a array.
input :
-0005
0003
-87
output :
-5
3
-87
I was also wondering what regex I could use to get this.
the words before the arrow are input and after is the output
the text is in french. And right now I am using this it works but not with the apostrophe.
String [] tab = txaTexte.getText().split("(?:(?<![a-zA-Z])'|'(?![a-zA-Z])|[^a-zA-Z'])+")
Un beau JOUR. —> Un/beau/JOUR
La boîte crânienne —> La/boîte/crânienne
C’était mieux aujourd’hui —> C’/était/mieux/aujourd’hui
qu’autrefois —> qu’/autrefois
D’hier jusqu’à demain! —> D’/hier/jusqu’/à/demain
Dans mon sous-sol—> Dans/mon/sous-sol
You might capture an optional hyphen, then match 1+ more times a zero and 1 capture 1 or more digits in group 2 starting with a digit 1-9
^(-?)0+([1-9]\d*)$
^ Start of string
(-?) Capture group 1, match optional hyphen
0+ Match 0+ zeroes
([1-9]\d*) Capture group 2, match 1+ digits starting with a digit 1-9
$ End of string
See a regex demo.
In the replacement use group 1 and group 2.
String regex = "^(-?)0+([1-9]\\d*)$";
String text = "-0005";
String numbers = txaTexte.getText().replaceAll(regex, "$1$2");
Here is one way. This preserves the sign.
capture the optional sign.
check for 0 or more leading zeros
followed by 1 or more digits.
String regex = "^([+-])?0*(\\d+)";
String [] data = {"-1415", "+2924", "-0000123", "000322", "+000023"};
for (String num : data) {
String after = num.replaceAll(regex, "$1$2");
System.out.printf("%8s --> %s%n", num , after);
}
prints
-1415 --> -1415
+2924 --> +2924
-0000123 --> -123
000322 --> 322
+000023 --> +23
If you want to keep -000, 000, +0000 etc. as just 0, try this regex:
`^[-+]?0*(0)$|^([-+])?0*(\d+)$`
Break down:
^...$ means the entire string should match (^ is the start of the string, $ is the end)
...|... is an alternative
[-+] is a character class that contains only the plus and minus characters. Note that - has a special meaning ("range") in character classes if it's not the first or last character
(...) is a capturing group which can be referenced in the replacement string by $number where number is the 1-based and 1-digit position of the group within the regex (the first group to start is no. 1 etc.)
?, * and + are quantifiers when used outside character classes meaning "0 or 1 occurence" (?), "any number of occurences, including none" (*) and "at least one occurence" (+)
^[-+]?0*(0)$ thus means: the entire string must be an optional sign, followed by any number of zeros and ending with a single zero which is captured as group 1.
alternatively ^([-+])?0*(\d+)$ means the entire string must be an optional sign which is captured as group 2, followed by any number of zeros and ending in at least one digit which is captured as group 3.
This regex can then be used with String.replaceAll(regex, "$1$2$3") in order to keep only the single 0 from group 1 or the optional sign and the number without leading zeros from groups 2 and 3. Any empty groups will result empty strings, that's why this works.
However, regular expressions can be slow, especially if you have to process a lot of strings.
One thing to improve this would be to compile the pattern only once:
//compile the pattern once and reuse it
Pattern p = Pattern.compile("^[+-]?0*(0)$|^([+-])?0*(\\d+)$");
//build a matcher from the pattern and the input string, and do the replacement
String number = p.matcher(txaTexte.getText()).replaceAll("$1$2$3");
If you're working on a large number of strings (> 10000) you might want to use some specialized plain parsing without regex. Consider something like this, which on my machine is about 10x faster than the regex approach with reused pattern:
public static String stripLeadingZeros(String s) {
//nothing to do, return the string as is
if( s == null || s.isEmpty() ) {
return s;
}
char[] chars = s.toCharArray();
int usedChars = 0;
//check if the first character is the sign
boolean hasSign = false;
if(chars[0] == '-' || chars[0] == '+') {
hasSign = true;
usedChars++;
//special case: just a sign
if(chars.length == 1) {
return s;
}
}
//process the rest of the characters
boolean stripZeros = true;
for( int i = usedChars; i < chars.length; i++) {
//not a digit, this isn't a simple integer, stop processing and keep the original string
if( chars[i] < '0' || chars[i] > '9') {
return s;
}
//are we still in zero-stripping mode
if( stripZeros) {
if( chars[i] == '0') {
continue; //check next char
}
//we've found a non-zero char, keep it and end zero-stripping mode
if(chars[i] >= '1' && chars[i] <= '9') {
stripZeros = false;
}
}
//since we are ignoring leading zeros, we just move all digits of the actual number to the left
chars[usedChars++] = chars[i];
}
//handle special case of number 0 (with optional sign)
if( usedChars == (hasSign ? 1 : 0)) {
chars[0] = '0';
usedChars = 1;
}
return new String(chars,0, usedChars);
}
Suddenly noticed that trim() method removes CRLF - new line - characters also..:
String s = "str\r\n";
s = s.trim();
System.out.println("--");
System.out.print(s);
System.out.println("--");
Is it intended to do so?
Yes, see the doc:
Otherwise, let k be the index of the first character in the string
whose code is greater than '\u0020', and let m be the index of the
last character in the string whose code is greater than '\u0020'. A
new String object is created, representing the substring of this
string that begins with the character at index k and ends with the
character at index m-that is, the result of this.substring(k, m+1).
CR+LF: CR (U+000D) followed by LF (U+000A) less than U+0020
if instr(lv_my_name, ' ', -2) != length(lv_my_name) - 2 or length(lv_my_name) = 2 then
lv_my_name:= lv_my_name;
else
lv_my_name:= trim(substr(lv_my_name, 0, length(lv_my_name)-1));
end if;
if I were to write the same logic in Java, how do I do it?
INSTR(string, substring [, position [, occurrence] ] )
The INSTR functions search string for substring. [...] If a substring that is equal to substring is found, then the function returns an integer indicating the position of the first character of this substring. If no such substring is found, then the function returns zero.
position is an nonzero integer indicating the character of string where Oracle Database begins the search—that is, the position of the first character of the first substring to compare with substring. If position is negative, then Oracle counts backward from the end of string and then searches backward from the resulting position.
occurrence is an integer indicating which occurrence of substring in string Oracle should search for. The value of occurrence must be positive. If occurrence is greater than 1, then the database does not return on the first match but continues comparing consecutive substrings of string, as described above, until match number occurrence has been found.
Compare that to:
String.indexOf(String str, int fromIndex)
Returns the index of the first occurrence of the specified substring, starting at the specified index, or -1 if there is no such occurrence.
String.lastIndexOf(String str, int fromIndex)
Returns the index of the last occurrence of the specified substring, searching backward from the specified index, or -1 if there is no such occurrence.
So, since your code doesn't use 4th parameter, and the 3rd parameter is negative, INSTR and lastIndexOf are mostly equivalent
Remember that Java indexes are 0-based, and Oracle positions are 1-based.
I am new to programming and working on a Java String assignment. The question says:
Declare a variable of type String named middle3 (put your declaration with the other declarations near the top of the program) and use an assignment statement and thesubstring method to assign middle3 the substring consisting of the middle three characters of phrase (the character at the middle index together with the character to the left of that and the one to the right). Add a println statement to print out the result. Save, compile, and run to test what you have done so far.
Here is what I have done:
String phrase = new String ("This is a String test.");
String middle3 = new String ("tri"); //I want to print the middle 3 characters in "phrase" which I think is "tri".
middle3 = phrase.substring (9, 11); // this only prints out 1 letter instead of 3
System.out.println ("middle3: " + middle3);
Here is my output:
Original phrase: This is a String test.
Length of the phrase: 18 characters
middle3: S
I also think that there are 18 characters in the string "phrase", but if there isn't, please let me know. Thank you in advance for all your help!
Think about how to retrieve the middle 3 characters without hardcoding the bounds of the substring() method. You can use the length() method in this regard. For example, the middle character of a string of odd length will always be at index str.length()/2, while the two middle characters of a string of even length will always be at index str.length()/2 and (str.length()/2) - 1. So the definition of the three middle characters will be up to you. But for our sakes, we'll just make the 3 middle characters at indexes (str.length()/2)-1, str.length()/2, and (str.length()/2)+1. With this information you can modify this line of code you had before,
middle3 = phrase.substring (9, 11);
to
middle3 = phrase.substring (phrase.length()/2 - 1, phrase.length()/2 + 2);
As to why the original line of code you had before was returning only one letter, it has to do with the parameters of the substring method. The first parameter is inclusive, but the second parameter isn't. Therefore, you were only retrieving characters from 9 to 10.
This is a String test.
^^^
9,10,11 (11 is not included)
The three characters I pointed to are at indices 9, 10, and 11 respectively. You only retrieved the chars ' ' and 'S', which together is just " S". That explains the one-letter output before.
First off, there are 22 characters in phrase.
"This is a String test."
^^^^^^^^^^^^^^^^^^^^^^ --> 22
Note that spaces () count towards the character count. Additionally, String has a method length() which will give you this number.
String phrase = "This is a String test.";
int phraseLength = phrase.length(); //22
From there, we can get the middle three characters by working off of the value phraseLength/2. The middle three characters would start one before the middle position, and stop one afterwards. However, because the string(int, int) method takes the end index to be exclusive, we should increase it by one.
String phrase = "This is a String test.";
int phraseLength = phrase.length(); //22
String middle3 = phrase.substring(phraseLength/2 - 1, phraseLength/2 + 2); // will have the middle 3 chars.
If the length of phrase is odd, this will return it middle 3 chars. If the length of phrase is even (as it is here), this will return the left-middle 3 chars. (For example, in 1,2,3,4, I'm using left-middle to represent 2 and right-middle to represent 3).
Another note, it's both unnecessary and bad practice to write new String("asdf"). Simply use the string literal instead.
String phrase = new String ("This is a String test."); //Bad
String phrase = "This is a String test."; //Good
you have an error in the begind index and the end index in the string, this is the correct code:
String phrase = new String("This is a String test.");
String middle3 = phrase.substring(11, 14);
System.out.println("middle3: " + middle3);
Before Java 8 when we split on empty string like
String[] tokens = "abc".split("");
split mechanism would split in places marked with |
|a|b|c|
because empty space "" exists before and after each character. So as result it would generate at first this array
["", "a", "b", "c", ""]
and later will remove trailing empty strings (because we didn't explicitly provide negative value to limit argument) so it will finally return
["", "a", "b", "c"]
In Java 8 split mechanism seems to have changed. Now when we use
"abc".split("")
we will get ["a", "b", "c"] array instead of ["", "a", "b", "c"].
My first guess was that maybe now leading empty strings are also removed just like trailing empty strings.
But this theory fails, since
"abc".split("a")
returns ["", "bc"], so leading empty string was not removed.
Can someone explain what is going on here? How rules of split have changed in Java 8?
The behavior of String.split (which calls Pattern.split) changes between Java 7 and Java 8.
Documentation
Comparing between the documentation of Pattern.split in Java 7 and Java 8, we observe the following clause being added:
When there is a positive-width match at the beginning of the input sequence then an empty leading substring is included at the beginning of the resulting array. A zero-width match at the beginning however never produces such empty leading substring.
The same clause is also added to String.split in Java 8, compared to Java 7.
Reference implementation
Let us compare the code of Pattern.split of the reference implemetation in Java 7 and Java 8. The code is retrieved from grepcode, for version 7u40-b43 and 8-b132.
Java 7
public String[] split(CharSequence input, int limit) {
int index = 0;
boolean matchLimited = limit > 0;
ArrayList<String> matchList = new ArrayList<>();
Matcher m = matcher(input);
// Add segments before each match found
while(m.find()) {
if (!matchLimited || matchList.size() < limit - 1) {
String match = input.subSequence(index, m.start()).toString();
matchList.add(match);
index = m.end();
} else if (matchList.size() == limit - 1) { // last one
String match = input.subSequence(index,
input.length()).toString();
matchList.add(match);
index = m.end();
}
}
// If no match was found, return this
if (index == 0)
return new String[] {input.toString()};
// Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString());
// Construct result
int resultSize = matchList.size();
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
resultSize--;
String[] result = new String[resultSize];
return matchList.subList(0, resultSize).toArray(result);
}
Java 8
public String[] split(CharSequence input, int limit) {
int index = 0;
boolean matchLimited = limit > 0;
ArrayList<String> matchList = new ArrayList<>();
Matcher m = matcher(input);
// Add segments before each match found
while(m.find()) {
if (!matchLimited || matchList.size() < limit - 1) {
if (index == 0 && index == m.start() && m.start() == m.end()) {
// no empty leading substring included for zero-width match
// at the beginning of the input char sequence.
continue;
}
String match = input.subSequence(index, m.start()).toString();
matchList.add(match);
index = m.end();
} else if (matchList.size() == limit - 1) { // last one
String match = input.subSequence(index,
input.length()).toString();
matchList.add(match);
index = m.end();
}
}
// If no match was found, return this
if (index == 0)
return new String[] {input.toString()};
// Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString());
// Construct result
int resultSize = matchList.size();
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
resultSize--;
String[] result = new String[resultSize];
return matchList.subList(0, resultSize).toArray(result);
}
The addition of the following code in Java 8 excludes the zero-length match at the beginning of the input string, which explains the behavior above.
if (index == 0 && index == m.start() && m.start() == m.end()) {
// no empty leading substring included for zero-width match
// at the beginning of the input char sequence.
continue;
}
Maintaining compatibility
Following behavior in Java 8 and above
To make split behaves consistently across versions and compatible with the behavior in Java 8:
If your regex can match zero-length string, just add (?!\A) at the end of the regex and wrap the original regex in non-capturing group (?:...) (if necessary).
If your regex can't match zero-length string, you don't need to do anything.
If you don't know whether the regex can match zero-length string or not, do both the actions in step 1.
(?!\A) checks that the string does not end at the beginning of the string, which implies that the match is an empty match at the beginning of the string.
Following behavior in Java 7 and prior
There is no general solution to make split backward-compatible with Java 7 and prior, short of replacing all instance of split to point to your own custom implementation.
This has been specified in the documentation of split(String regex, limit).
When there is a positive-width match at the beginning of this string
then an empty leading substring is included at the beginning of the
resulting array. A zero-width match at the beginning however never
produces such empty leading substring.
In "abc".split("") you got a zero-width match at the beginning so the leading empty substring is not included in the resulting array.
However in your second snippet when you split on "a" you got a positive width match (1 in this case), so the empty leading substring is included as expected.
(Removed irrelevant source code)
There was a slight change in the docs for split() from Java 7 to Java 8. Specifically, the following statement was added:
When there is a positive-width match at the beginning of this string then an empty leading substring is included at the beginning of the resulting array. A zero-width match at the beginning however never produces such empty leading substring.
(emphasis mine)
The empty string split generates a zero-width match at the beginning, so an empty string is not included at the start of the resulting array in accordance with what is specified above. By contrast, your second example which splits on "a" generates a positive-width match at the start of the string, so an empty string is in fact included at the start of the resulting array.