Please explain me this code of Delimiter matching with stacks - java

/** Test if delimiters in the given expression are properly matched. */
public static boolean isMatched(String expression) {
final String opening = "({["; // opening delimiters
final String closing = ")}]"; // respective closing delimiters
Stack<Character> buffer = new LinkedStack<>();
for (char c:expression.toCharArray()) {
if (opening.indexOf(c) != -1) // this is a left delimiter
buffer.push(c);
else if (closing.indexOf(c) != -1) { // this is a right delimiter
if (buffer.isEmpty()) // nothing to match with
return false;
if (closing.indexOf(c) != opening.indexOf(buffer.pop()))
return false; // mismatched delimiter
}
}
return buffer.isEmpty(); // were all opening delimiters matched?
}
Assume a generic stack interface, Stack<E> with unimplemented methods: push( E ), pop(), isEmpty() where E is a generic data type.
And a LinkedArray<E> class implementing all Stacks<E> methods.
'expression' in 'isMatched()' is a mathematical expression with braces as delimiters. Ex- [{(a+b)*(c+d)}]; and
isMatched(String expression) is a method to check whether the expression contains correctly paired braces.
buffer is a stack to store the pushed expression's (now an array of char) members.
I am able to understand the code till the for-each loop.
And the lines after that are eating me.

The indexOf("c") method is used to return the index of first occurence of c in the given string. For example String s=" java";
int i= s.indexOf("a");
would set i = 1

Related

most efficient way to check if a string contains specific characters

I have a string that should contain only specific characters: {}()[]
I've created a validate method that checks if the string contains forbidden characters (by forbidden characters I mean everything that is not {}()[] )
Here is my code:
private void validate(String string) {
char [] charArray = string.toCharArray();
for (Character c : charArray) {
if (!"{}()[]".contains(c.toString())){
throw new IllegalArgumentException("The string contains forbidden characters");
}
}
}
I'm wondering if there are better ways to do it since my approach doesn't seem right.
If I took the way you implement this, I would personally modify it like below:
private static void validate(String str) {
for (char c : str.toCharArray()) {
if ("{}()[]".indexOf(c) < 0){
throw new IllegalArgumentException("The string contains forbidden characters");
}
}
}
The changes are as follows:
Not declaring a temporary variable for the char array.
Using indexOf to find a character instead of converting c to String to use .contains().
Looping on the primitive char since you no longer need
toString().
Not naming the parameter string as this can cause confusion and is not good practice.
Note: contains calls indexOf(), so this does also technically save you a method call each iteration.
I'd suggest using Stream if you are using Java 8.
This allow you omit char to String boxing stuff.
private void validate_stream(String str) {
if(str.chars().anyMatch(a -> a==125||a==123||a==93||a==91||a==41||a==40))
throw new IllegalArgumentException("The string contains forbidden characters");
}
The numbers are ASCII codes for forbidden characters, you can replace them with chars if you want:
(a -> a=='{'||a=='}'||a=='['||a==']'||a=='('||a==')')
I hope this works for you: I have added my code along with your code.
I have used a regex pattern, where \\ escapes brackets, which has special meaning in regex. And use matches method of string, it try to matches the given string value with given reg ex pattern. In this case as we used not(!), if we give string like "{}()[]as", it satisfies the if not condition and prints "not matched", otherwise if we give string like "{}()[]", else case will will print. You can change this how you like by throwing exception.
private static void validate(String string)
{
String pattern = "\\{\\}\\(\\)\\[\\]";
if(!string.matches(pattern)) {
System.out.println("not matched:"+string);
}
else {
System.out.println("data matched:"+string);
}
char [] charArray = string.toCharArray();
for (Character c : charArray) {
if (!"{}()[]".contains(c.toString())){
throw new IllegalArgumentException("The string contains forbidden characters");
}
}
}
All the brackets are Meta characters, referenced here:
http://tutorials.jenkov.com/java-regex/index.html

How to create a method that checks for pattern in string and return the character after the pattern using an ArrayList? (Prompt in description)

Method Name - getCharsThatFollowPattern
Prompt and what its supposed to do. Takes a String text and a String pattern as parameters, and returns an ArrayList. The returned list should contain the character that follows each non-tail occurrence of the pattern in the text. (A non-tail occurrence of the pattern is one that is not at the very end of the text.) The length of the list must be the same as the number of non-tail occurrences of the pattern. The character stored at index n of the list must be the character that followed the nth non-tail occurrence of the pattern. For example, getCharsThatFollowPattern("abcabdabcab", "ab") should return the ArrayList ['c', 'd', 'c'].
My code is below along with the results.
public static ArrayList<Character> getCharsThatFollowPattern (String text, String pattern)
{
ArrayList<Character> character = new ArrayList<>();
// String str = text;
// String findStr = pattern;
int lastIndex = 0;
while (lastIndex != -1) {
lastIndex = text.indexOf(pattern, lastIndex);
if (lastIndex != -1) {
lastIndex += pattern.length();
char c = text.charAt(text.lastIndexOf(pattern) - 1);
character.add(c);
}
}
return character;
}
The results of the code are as follow.
getCharsThatFollowPattern("abcabdabcab", "ab") returns [c,c,c,c];
- which is wrong.
getCharsThatFollowPattern("abababa", "aba") returns [b, b];
- which is what its supposed to do.
My teacher supplied me with a test case that works but when I tested it myself it does not work.
#Test
public void testGetCharsThatFollowPattern ()
{
ArrayList<Character> list = new ArrayList<Character>();
list.add('b');
list.add('b');
assertEquals(list,
PS5Library.getCharsThatFollowPattern("abababa", "aba"));
}
}
I have been scavenging stack overflow and cannot find an answer to my question. Any insights on to why how to fix this would be great. Thank you guys.
I think you just have a small math error and just need to change the line that assigns c to this:
char c = text.charAt(lastIndex);
You already accepted an answer but the reason why you always added c is the following line:
char c = text.charAt(text.lastIndexOf(pattern) - 1);
You always look for the character after the last occurrence of the pattern. The StringIndexOutOfBoundsException results from the fact that the text ends with the pattern without subsequent character. The index itself is zero-indexed, so charAt(5) tries to access the 6th character of a five-character-long text.
You might ignore the exception or check the length of the text with the index and only call charAt(index) if index < text.length(). The latter would prevent unnecessary creations of Exceptions and it's better style, too ;-)

Checking for a not null, not blank String in Java

I am trying to check if a Java String is not null, not empty and not whitespace.
In my mind, this code should have been quite up for the job.
public static boolean isEmpty(String s) {
if ((s != null) && (s.trim().length() > 0))
return false;
else
return true;
}
As per documentation, String.trim() should work thus:
Returns a copy of the string, with leading and trailing whitespace omitted.
If this String object represents an empty character sequence, or the first and last characters of character sequence represented by this String object both have codes greater than '\u0020' (the space character), then a reference to this String object is returned.
However, apache/commons/lang/StringUtils.java does it a little differently.
public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
As per documentation, Character.isWhitespace():
Determines if the specified character is white space according to Java. A character is a Java whitespace character if and only if it satisfies one of the following criteria:
It is a Unicode space character (SPACE_SEPARATOR, LINE_SEPARATOR, or PARAGRAPH_SEPARATOR) but is not also a non-breaking space ('\u00A0', '\u2007', '\u202F').
It is '\t', U+0009 HORIZONTAL TABULATION.
It is '\n', U+000A LINE FEED.
It is '\u000B', U+000B VERTICAL TABULATION.
It is '\f', U+000C FORM FEED.
It is '\r', U+000D CARRIAGE RETURN.
It is '\u001C', U+001C FILE SEPARATOR.
It is '\u001D', U+001D GROUP SEPARATOR.
It is '\u001E', U+001E RECORD SEPARATOR.
It is '\u001F', U+001F UNIT SEPARATOR.
If I am not mistaken - or might be I am just not reading it correctly - the String.trim() should take away any of the characters that are being checked by Character.isWhiteSpace(). All of them see to be above '\u0020'.
In this case, the simpler isEmpty function seems to be covering all the scenarios that the lengthier isBlank is covering.
Is there a string that will make the isEmpty and isBlank behave differently in a test case?
Assuming there are none, is there any other consideration because of which I should choose isBlank and not use isEmpty?
For those interested in actually running a test, here are the methods and unit tests.
public class StringUtil {
public static boolean isEmpty(String s) {
if ((s != null) && (s.trim().length() > 0))
return false;
else
return true;
}
public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
}
And unit tests
#Test
public void test() {
String s = null;
assertTrue(StringUtil.isEmpty(s)) ;
assertTrue(StringUtil.isBlank(s)) ;
s = "";
assertTrue(StringUtil.isEmpty(s)) ;
assertTrue(StringUtil.isBlank(s));
s = " ";
assertTrue(StringUtil.isEmpty(s)) ;
assertTrue(StringUtil.isBlank(s)) ;
s = " ";
assertTrue(StringUtil.isEmpty(s)) ;
assertTrue(StringUtil.isBlank(s)) ;
s = " a ";
assertTrue(StringUtil.isEmpty(s)==false) ;
assertTrue(StringUtil.isBlank(s)==false) ;
}
Update: It was a really interesting discussion - and this is why I love Stack Overflow and the folks here. By the way, coming back to the question, we got:
A program showing which all characters will make the behave differently. The code is at https://ideone.com/ELY5Wv. Thanks #Dukeling.
A performance related reason for choosing the standard isBlank(). Thanks #devconsole.
A comprehensive explanation by #nhahtdh. Thanks mate.
Is there a string that will make the isEmpty and isBlank behave differently in a test case?
Note that Character.isWhitespace can recognize Unicode characters and return true for Unicode whitespace characters.
Determines if the specified character is white space according to Java. A character is a Java whitespace character if and only if it satisfies one of the following criteria:
It is a Unicode space character (SPACE_SEPARATOR, LINE_SEPARATOR, or PARAGRAPH_SEPARATOR) but is not also a non-breaking space ('\u00A0', '\u2007', '\u202F').
[...]
On the other hand, trim() method would trim all control characters whose code points are below U+0020 and the space character (U+0020).
Therefore, the two methods would behave differently at presence of a Unicode whitespace character. For example: "\u2008". Or when the string contains control characters that are not consider whitespace by Character.isWhitespace method. For example: "\002".
If you were to write a regular expression to do this (which is slower than doing a loop through the string and check):
isEmpty() would be equivalent to .matches("[\\x00-\\x20]*")
isBlank() would be equivalent to .matches("\\p{javaWhitespace}*")
(The isEmpty() and isBlank() method both allow for null String reference, so it is not exactly equivalent to the regex solution, but putting that aside, it is equivalent).
Note that \p{javaWhitespace}, as its name implied, is Java-specific syntax to access the character class defined by Character.isWhitespace method.
Assuming there are none, is there any other consideration because of which I should choose isBlank and not use isEmpty?
It depends. However, I think the explanation in the part above should be sufficient for you to decide. To sum up the difference:
isEmpty() will consider the string is empty if it contains only control characters1 below U+0020 and space character (U+0020)
isBlank will consider the string is empty if it contains only whitespace characters as defined by Character.isWhitespace method, which includes Unicode whitespace characters.
1 There is also the control character at U+007F DELETE, which is not trimmed by trim() method.
The purpose of the two standard methods is to distinguish between this two cases:
org.apache.common.lang.StringUtils.isBlank(" ") (will return true).
org.apache.common.lang.StringUtils.isEmpty(" ") (will return false).
Your custom implementation of isEmpty() will return true.
UPDATE:
org.apache.common.lang.StringUtils.isEmpty() is used to find if the String is length 0 or null.
org.apache.common.lang.StringUtils.isBlank() takes it a step forward. It not only checks if the String is length 0 or null, but also checks if it is only a whitespace string.
In your case, you're trimming the String in your isEmpty method. The only difference that can occur now can't occur (the case you gives it " ") because you're trimming it (Removing the trailing whitespace - which is in this case is like removing all spaces).
I would choose isBlank() over isEmpty() because trim() creates a new String object that has to be garbage collected later. isBlank() on the other hand does not create any objects.
You could take a look at JSR 303 Bean Validtion wich contains the Annotatinos #NotEmpty and #NotNull. Bean Validation is cool because you can seperate validation issues from the original intend of the method.
Why can't you simply use a nested ternary operator to achieve this.Please look into the sample code
public static void main(String[] args)
{
String s = null;
String s1="";
String s2="hello";
System.out.println(" 1 "+check(s));
System.out.println(" 2 "+check(s1));
System.out.println(" 3 "+check(s2));
}
public static boolean check(String data)
{
return (data==null?false:(data.isEmpty()?false:true));
}
and the output is as follows
1 false 2 false 3 true
here the 1st 2 scenarios returns false (i.e null and empty)and the 3rd scenario returns true
<%
System.out.println(request.getParameter("userName")+"*");
if (request.getParameter("userName").trim().length() == 0 | request.getParameter("userName") == null) { %>
<jsp:forward page="HandleIt.jsp" />
<% }
else { %>
Hello ${param.userName}
<%} %>
This simple code will do enough:
public static boolean isNullOrEmpty(String str) {
return str == null || str.trim().equals("");
}
And the unit tests:
#Test
public void testIsNullOrEmpty() {
assertEquals(true, AcdsUtils.isNullOrEmpty(""));
assertEquals(true, AcdsUtils.isNullOrEmpty((String) null));
assertEquals(false, AcdsUtils.isNullOrEmpty("lol "));
assertEquals(false, AcdsUtils.isNullOrEmpty("HallO"));
}
With Java 8, you could also use the Optional capability with filtering. To check if a string is blank, the code is pure Java SE without additional library.
The following code illustre a isBlank() implementation.
String.trim() behaviour
!Optional.ofNullable(tocheck).filter(e -> e != null && e.trim().length() > 0).isPresent()
StringUtils.isBlank() behaviour
Optional.ofNullable(toCheck)
.filter(e ->
{
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
})
.isPresent()

why did it not split?

i am confused on why it doest not split the string? my array of string exp does not contain anything when i debug it is the split wrong?what i am trying to do is to split a very simple expression like 1+2+3 and then parse the values, doing a calculator.
EDIT
hi, why i am splitting on each character is because i am doing a calculator, and have read something about converting infix to postfix,so i need to split the string and then loop through each of the string and do the checking as shown below,however when i debug it shows the exp[] is empty
For each token in turn in the input infix expression:
* If the token is an operand, append it to the postfix output.
* If the token is an operator A then:
o While there is an operator B of higher or equal precidence than A at the top of the stack, pop B off the stack and append it to the output.
o Push A onto the stack.
* If the token is an opening bracket, then push it onto the stack.
* If the token is a closing bracket:
o Pop operators off the stack and append them to the output, until the operator at the top of the stack is a opening bracket.
o Pop the opening bracket off the stack.
When all the tokens have been read:
* While there are still operator tokens in the stack:
o Pop the operator on the top of the stack, and append it to the output.
// the main class
public class Main {
public static void main(String[] args) {
calcExpChecker calc = new calcExpChecker("1+2+3+4");
calc.legitExp();
calc.displayPostfix();
}
}
//the class
package javaapplication4;
import java.util.*;
public class calcExpChecker {
private String originalExp; // the orginal display passed
private boolean isItLegitExp; // the whole expression is it legit
private boolean isItBlank; // is the display blank?
private StringBuilder expression = new StringBuilder(50);
private Stack stack = new Stack();//stack for making a postfix string
calcExpChecker(String original)
{
originalExp = original;
}
//check for blank expression
public void isitBlank()
{
if(originalExp.equals(""))
{
isItBlank = true;
}
else
{
isItBlank = false;
}
}
//check for extra operators
public void legitExp()
{
String[] exp = originalExp.split(".");
for(int i = 0 ; i < exp.length ; i++)
{
if(exp[i].matches("[0-9]"))
{
expression.append(exp[i]);
}
else if(exp[i].matches("[+]"))
{
if(stack.empty())
{
stack.push(exp[i]);
}
else
{
while(stack.peek().equals("+"))
{
expression.append(stack.pop());
}
stack.push(exp[i]);
}
}
if (!stack.empty())
{
expression.append(stack.pop());
}
}
}
public void displayPostfix()
{
System.out.print(expression.toString());
}
}
If you make every character a delimiter, what is between them? Nothing
e.g.,
1+2+3+4
is 1 a delimiter? yes, ok, capture everything between it and the next delimiter. Next delimiter? +. Nothing captured. Next delimiter? 2. etc etc
You want to split on every character, so rather use string.split("").
for (String part : string.split("")) {
// ...
}
Or better, just iterate over every character returned by string.toCharArray().
for (char c : string.toCharArray()) {
// ...
}
With chars you can use a switch statement which is better than a large if/else block.
why do you need to split on each character & rather not go for foreach character in the String. That way you don't have to reference as exp[i] either.
Anyways you can split using "" instead of "."
Confession:
Okay I guess my answer is bad because there are subtle differences between Java and C# with this stuff. Still, maybe it'll help someone with the same problem but in C#!
Btw, in C#, if you pass in a RegEx "." you don't get an empty array, instead you get an array of blanks (""), one for each character boundary in the string.
Edit
You can pass a regex expression into the split() function:
string expressions = "10+20*4/2";
/* this will separate the string into an array of numbers and the operators;
the numbers will be together rather than split into individual characters
as "" or "." would do;
this should make processing the expression easier
gives you: {"10", "+", "20", "*", "4", "/", "2"} */
foreach (string exp in expressions.split(#"(\u002A)|(\u002B)|(\u002D)|(\u002F)"))
{
//process each number or operator from the array in this loop
}
Original
String[] exp = originalExp.split(".");
You should get at least one string from the return value of split() (the original un-split string). If the array of strings is empty, the original string was probably empty.
Java String Split() Method

How can I check if a single character appears in a string?

In Java is there a way to check the condition:
"Does this single character appear at all in string x"
without using a loop?
You can use string.indexOf('a').
If the char a is present in string :
it returns the the index of the first occurrence of the character in
the character sequence represented by this object, or -1 if the
character does not occur.
String.contains() which checks if the string contains a specified sequence of char values
String.indexOf() which returns the index within the string of the first occurence of the specified character or substring (there are 4 variations of this method)
I'm not sure what the original poster is asking exactly. Since indexOf(...) and contains(...) both probably use loops internally, perhaps he's looking to see if this is possible at all without a loop? I can think of two ways off hand, one would of course be recurrsion:
public boolean containsChar(String s, char search) {
if (s.length() == 0)
return false;
else
return s.charAt(0) == search || containsChar(s.substring(1), search);
}
The other is far less elegant, but completeness...:
/**
* Works for strings of up to 5 characters
*/
public boolean containsChar(String s, char search) {
if (s.length() > 5) throw IllegalArgumentException();
try {
if (s.charAt(0) == search) return true;
if (s.charAt(1) == search) return true;
if (s.charAt(2) == search) return true;
if (s.charAt(3) == search) return true;
if (s.charAt(4) == search) return true;
} catch (IndexOutOfBoundsException e) {
// this should never happen...
return false;
}
return false;
}
The number of lines grow as you need to support longer and longer strings of course. But there are no loops/recurrsions at all. You can even remove the length check if you're concerned that that length() uses a loop.
You can use 2 methods from the String class.
String.contains() which checks if the string contains a specified sequence of char values
String.indexOf() which returns the index within the string of the first occurence of the specified character or substring or returns -1 if the character is not found (there are 4 variations of this method)
Method 1:
String myString = "foobar";
if (myString.contains("x") {
// Do something.
}
Method 2:
String myString = "foobar";
if (myString.indexOf("x") >= 0 {
// Do something.
}
Links by: Zach Scrivena
String temp = "abcdefghi";
if(temp.indexOf("b")!=-1)
{
System.out.println("there is 'b' in temp string");
}
else
{
System.out.println("there is no 'b' in temp string");
}
If you need to check the same string often you can calculate the character occurrences up-front. This is an implementation that uses a bit array contained into a long array:
public class FastCharacterInStringChecker implements Serializable {
private static final long serialVersionUID = 1L;
private final long[] l = new long[1024]; // 65536 / 64 = 1024
public FastCharacterInStringChecker(final String string) {
for (final char c: string.toCharArray()) {
final int index = c >> 6;
final int value = c - (index << 6);
l[index] |= 1L << value;
}
}
public boolean contains(final char c) {
final int index = c >> 6; // c / 64
final int value = c - (index << 6); // c - (index * 64)
return (l[index] & (1L << value)) != 0;
}}
To check if something does not exist in a string, you at least need to look at each character in a string. So even if you don't explicitly use a loop, it'll have the same efficiency. That being said, you can try using str.contains(""+char).
Is the below what you were looking for?
int index = string.indexOf(character);
return index != -1;
Yes, using the indexOf() method on the string class. See the API documentation for this method
String.contains(String) or String.indexOf(String) - suggested
"abc".contains("Z"); // false - correct
"zzzz".contains("Z"); // false - correct
"Z".contains("Z"); // true - correct
"πŸ˜€andπŸ˜€".contains("πŸ˜€"); // true - correct
"πŸ˜€andπŸ˜€".contains("πŸ˜‚"); // false - correct
"πŸ˜€andπŸ˜€".indexOf("πŸ˜€"); // 0 - correct
"πŸ˜€andπŸ˜€".indexOf("πŸ˜‚"); // -1 - correct
String.indexOf(int) and carefully considered String.indexOf(char) with char to int widening
"πŸ˜€andπŸ˜€".indexOf("πŸ˜€".charAt(0)); // 0 though incorrect usage has correct output due to portion of correct data
"πŸ˜€andπŸ˜€".indexOf("πŸ˜‚".charAt(0)); // 0 -- incorrect usage and ambiguous result
"πŸ˜€andπŸ˜€".indexOf("πŸ˜‚".codePointAt(0)); // -1 -- correct usage and correct output
The discussions around character is ambiguous in Java world
can the value of char or Character considered as single character?
No. In the context of unicode characters, char or Character can sometimes be part of a single character and should not be treated as a complete single character logically.
if not, what should be considered as single character (logically)?
Any system supporting character encodings for Unicode characters should consider unicode's codepoint as single character.
So Java should do that very clear & loud rather than exposing too much of internal implementation details to users.
String class is bad at abstraction (though it requires confusingly good amount of understanding of its encapsulations to understand the abstraction πŸ˜’πŸ˜’πŸ˜’ and hence an anti-pattern).
How is it different from general char usage?
char can be only be mapped to a character in Basic Multilingual Plane.
Only codePoint - int can cover the complete range of Unicode characters.
Why is this difference?
char is internally treated as 16-bit unsigned value and could not represent all the unicode characters using UTF-16 internal representation using only 2-bytes. Sometimes, values in a 16-bit range have to be combined with another 16-bit value to correctly define character.
Without getting too verbose, the usage of indexOf, charAt, length and such methods should be more explicit. Sincerely hoping Java will add new UnicodeString and UnicodeCharacter classes with clearly defined abstractions.
Reason to prefer contains and not indexOf(int)
Practically there are many code flows that treat a logical character as char in java.
In Unicode context, char is not sufficient
Though the indexOf takes in an int, char to int conversion masks this from the user and user might do something like str.indexOf(someotherstr.charAt(0))(unless the user is aware of the exact context)
So, treating everything as CharSequence (aka String) is better
public static void main(String[] args) {
System.out.println("πŸ˜€andπŸ˜€".indexOf("πŸ˜€".charAt(0))); // 0 though incorrect usage has correct output due to portion of correct data
System.out.println("πŸ˜€andπŸ˜€".indexOf("πŸ˜‚".charAt(0))); // 0 -- incorrect usage and ambiguous result
System.out.println("πŸ˜€andπŸ˜€".indexOf("πŸ˜‚".codePointAt(0))); // -1 -- correct usage and correct output
System.out.println("πŸ˜€andπŸ˜€".contains("πŸ˜€")); // true - correct
System.out.println("πŸ˜€andπŸ˜€".contains("πŸ˜‚")); // false - correct
}
Semantics
char can handle most of the practical use cases. Still its better to use codepoints within programming environment for future extensibility.
codepoint should handle nearly all of the technical use cases around encodings.
Still, Grapheme Clusters falls out of the scope of codepoint level of abstraction.
Storage layers can choose char interface if ints are too costly(doubled). Unless storage cost is the only metric, its still better to use codepoint. Also, its better to treat storage as byte and delegate semantics to business logic built around storage.
Semantics can be abstracted at multiple levels. codepoint should become lowest level of interface and other semantics can be built around codepoint in runtime environment.
package com;
public class _index {
public static void main(String[] args) {
String s1="be proud to be an indian";
char ch=s1.charAt(s1.indexOf('e'));
int count = 0;
for(int i=0;i<s1.length();i++) {
if(s1.charAt(i)=='e'){
System.out.println("number of E:=="+ch);
count++;
}
}
System.out.println("Total count of E:=="+count);
}
}
static String removeOccurences(String a, String b)
{
StringBuilder s2 = new StringBuilder(a);
for(int i=0;i<b.length();i++){
char ch = b.charAt(i);
System.out.println(ch+" first index"+a.indexOf(ch));
int lastind = a.lastIndexOf(ch);
for(int k=new String(s2).indexOf(ch);k > 0;k=new String(s2).indexOf(ch)){
if(s2.charAt(k) == ch){
s2.deleteCharAt(k);
System.out.println("val of s2 : "+s2.toString());
}
}
}
System.out.println(s1.toString());
return (s1.toString());
}
you can use this code. It will check the char is present or not. If it is present then the return value is >= 0 otherwise it's -1. Here I am printing alphabets that is not present in the input.
import java.util.Scanner;
public class Test {
public static void letters()
{
System.out.println("Enter input char");
Scanner sc = new Scanner(System.in);
String input = sc.next();
System.out.println("Output : ");
for (char alphabet = 'A'; alphabet <= 'Z'; alphabet++) {
if(input.toUpperCase().indexOf(alphabet) < 0)
System.out.print(alphabet + " ");
}
}
public static void main(String[] args) {
letters();
}
}
//Ouput Example
Enter input char
nandu
Output :
B C E F G H I J K L M O P Q R S T V W X Y Z
If you see the source code of indexOf in JAVA:
public int indexOf(int ch, int fromIndex) {
final int max = value.length;
if (fromIndex < 0) {
fromIndex = 0;
} else if (fromIndex >= max) {
// Note: fromIndex might be near -1>>>1.
return -1;
}
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
final char[] value = this.value;
for (int i = fromIndex; i < max; i++) {
if (value[i] == ch) {
return i;
}
}
return -1;
} else {
return indexOfSupplementary(ch, fromIndex);
}
}
you can see it uses a for loop for finding a character. Note that each indexOf you may use in your code, is equal to one loop.
So, it is unavoidable to use loop for a single character.
However, if you want to find a special string with more different forms, use useful libraries such as util.regex, it deploys stronger algorithm to match a character or a string pattern with Regular Expressions. For example to find an email in a string:
String regex = "^(.+)#(.+)$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(email);
If you don't like to use regex, just use a loop and charAt and try to cover all cases in one loop.
Be careful recursive methods has more overhead than loop, so it's not recommended.
how about one uses this ;
let text = "Hello world, welcome to the universe.";
let result = text.includes("world");
console.log(result) ....// true
the result will be a true or false
this always works for me
You won't be able to check if char appears at all in some string without atleast going over the string once using loop / recursion ( the built-in methods like indexOf also use a loop )
If the no. of times you look up if a char is in string x is more way more than the length of the string than I would recommend using a Set data structure as that would be more efficient than simply using indexOf
String s = "abc";
// Build a set so we can check if character exists in constant time O(1)
Set<Character> set = new HashSet<>();
int len = s.length();
for(int i = 0; i < len; i++) set.add(s.charAt(i));
// Now we can check without the need of a loop
// contains method of set doesn't use a loop unlike string's contains method
set.contains('a') // true
set.contains('z') // false
Using set you will be able to check if character exists in a string in constant time O(1) but you will also use additional memory ( Space complexity will be O(n) ).

Categories

Resources