removal of repeated string - java

I have a string something like
JNDI Locations eis/FileAdapter,eis/FileAdapter used by composite
HelloWorld1.0.jar are not available in the
destination domain.
eis/FileAdapter,eis/FileAdapter is occuring twice.
I want it to be formatted as
JNDI Locations eis/FileAdapter used by composite
HelloWorld1.0.jar are not available in the
destination domain.
I tried below thing
String[ ] missingAdapters =((textMissingAdapterList.item(0)).getNodeValue().trim().split(","));
missingAdapters.get(0)
but i am missing second part any better way to handle this?

In your comment below the question you confirm, that the duplicates will alway be conencted via a comma. Using this information, this should work (for most cases):
String replaceCustomDuplicates(String str) {
if (str.indexOf(",") < 0) {
return str; // nothing to do
}
StringBuilder result = new StringBuilder(str.length());
for (String token : str.split(" ", -1)) {
if (token.indexOf(",") > 0) {
String[] parts = token.split(",");
if (parts.length == 2 && parts[0].equals(parts[1])) {
token = parts[0];
}
}
result.append(token + " ");
}
return result.delete(result.length() - 1, result.length()).toString();
}
a little demo with your example:
String str = "JNDI Locations eis/FileAdapter,eis/FileAdapter used by composite";
System.out.println(str);
str = replaceCustomDuplicates(str);
System.out.println(str);
Previous errors fixed

That should do it:
String[] missingAdapters = ((textMissingAdapterList.item(0)).getNodeValue().trim().split(","));
String result = missingAdapters[0] + " " + missingAdapters[1].split(" ", 2)[1];
assuming there is no space in this double string you want to leave out.

Related

What's the best way to return concatenated Strings with checks for null or empty in Java?

I have two Strings, each one of them can be empty (blank or empty by StringUtils definition.) I need to display them in a concatenated fashion having a simple character in between, e.g. dash, comma, etc.
For example, a person's name consists of LastName and FirstName. PrintName method should print in this fashion:
case a: both not empty
print LastName + ", " FirstName
case b: FirstName is empty
print LastName
case c: LastName is empty
print FirstName
case d: both are empty
print empty string
This is just a simple exercise, but I'm curious if there's a most efficient method in Java that requires minimum variables/memory allocation, fewer lines of code, so on and so forth... My definition of efficiency is a bit vague so if you could write down why you think it's more efficient, that would be nice.
If it's just two strings, and they are empty, not null, I'd go with
System.out.println(
lastName
+ (( firstName.length() > 0 && lastName.length() > 0 ) ? ", " : "")
+ firstName
);
Explanation: the middle expression will be ", " only if both strings are non-empty.
In all other cases both the middle part and one or both of the others are empty. Thus, only the full side is printed.
If you want to go by StringUtils's definitions, the code is:
System.out.println(
StringUtils.stripToEmpty(lastName)
+ (( StringUtils.isNotBlank(firstName) && StringUtils.isNotBlank(lastName) ) ? ", " : "")
+ StringUtils.stripToEmpty(firstName)
);
You could design your pritning method like follows:
public class Main {
private final static Predicate<String> notEmpty = s -> s != null;
private final static Predicate<String> notBlank = s -> !s.equals("");
// ...
private static void printName(final String firstName, final String lastName) {
final boolean firstNameOk = notEmpty.and(notBlank).test(firstName);
final boolean lastNameOk = notEmpty.and(notBlank).test(lastName);
final StringBuilder result = new StringBuilder();
// Old version:
//result
// .append(lastNameOk ? lastName : "")
// .append(lastNameOk && firstNameOk ? ", " : "")
// .append(firstNameOk ? firstName : "");
// End of old Version:
// New version:
if (lastNameOk) {
result.append(lastName);
}
if (firstNameOk) {
if (lastNameOk) {
result.append(", ");
}
result.append(firstName);
}
// End of new version:
System.out.println(result);
}
}
Then some example calls:
public static void main(String[] args) {
printName("James", "Bond");
printName("James", null);
printName(null, "Bond");
printName(null, null);
}
Will print:
Bond, James
James
Bond
Only one boolean variable, but still four branches:
public void p(String f, String l) {
boolean e=l==null||l.isEmpty();
System.out.println(f==null||f.isEmpty()?e?"":l:e?f:f+", "+l);
}
This is surely not the best way and I would also recommend using Guava or another library like Apache commons.
return (firstName == null ? "" : firstname + ", " + lastName==null ? "" : lastName).replaceFirst("^, |, $","");
this will result in the firstname + ", " + lastname string, and in case the ", " string is at the beginning or the end of the string, it will be erased, therefore you get exactly what you want.
You can use apache commons api class to validate it in single line.
GenericValidator.isBlankOrNull(value);
For that you need to use apache commons jar and import this class
import org.apache.commons.validator.GenericValidator;
Try this one:
String LastName = "First";
String FirstName = "Last";
boolean cond1, cond2;
cond1 = FirstName == null || "".equals(FirstName);
cond2 = LastName == null || "".equals(LastName);
String DesiredName = (cond2 ? "" : LastName) +
((!cond2 && !cond1) ? ", " : "") +
(cond1 ? "" : FirstName);
System.out.println(DesiredName);
Use Google's guava and its Joiner method. It is the most elegant solution as far as I know.
https://code.google.com/p/guava-libraries/wiki/StringsExplained
Joiner joiner = Joiner.on(", ").skipNulls();
return joiner.join(firstName, lastName);
To skips nulls + empty strings, store firstName, lastName... in an array or list and then do
return Joiner.on(", ").join(Iterables.filter(listOfStrings, StringPredicates.notEmpty()));
You can look at the Joiner source code to see how its implemented. It is certainly not the most efficient but in this case the ignorable efficiency gain is worth trading off with code clarity and readability.
Clean, no extra conditions/libraries. This is of course specific to your requirement. You can use Guava's Joiner for more complex requirements.
public static void main(String[] args) throws Exception {
String firstName = "Stack";
String lastName = "Overflow";
System.out.println(printName(firstName, lastName));
}
private static String printName(String firstName, String lastName) {
StringBuilder buffer = new StringBuilder();
String cleanFirstName = avoidNull(firstName, "");
String cleanLastName = avoidNull(lastName, "");
if (!cleanLastName.isEmpty()) {
buffer.append(cleanLastName);
}
if (!cleanFirstName.isEmpty()) {
if (!cleanLastName.isEmpty()) {
buffer.append(", ");
}
buffer.append(cleanFirstName);
}
return buffer.toString();
}
private static String avoidNull(String str, String alternate) {
if (str == null || str.isEmpty()) {
return alternate;
}
return str;
}
You can remove the alternate parameter in the avoidNull() method if you don't want it.
private static String avoidNull(String str) {
return str == null ? "" : str;
}
I believe you shouldn't focus on performance this much, but on clean code.
If you have only two strings, you could create simple method as this one (I assume you are using Java 8).
public static String combine(String s1, String s2) {
StringJoiner sj = new StringJoiner(", ");
if (!StringUtils.isBlank(s1)) sj.add(s1);
if (!StringUtils.isBlank(s2)) sj.add(s2);
return sj.toString();
}
You can replace !StringUtils.isBlank(s1) with s1!=null %% !s1.trim().isEmpty()
If you want to create more generic method in which you could decide which delimiter to use, and which would be able to accept more than two Strings you could use something like
public static String joinWithourEmptyOrNull(String delimiter, String... words) {
StringJoiner sj = new StringJoiner(delimiter);
for (String s : words) {
if (!StringUtils.isBlank(s))
sj.add(s);
}
return sj.toString();
}
You can also rewrite this code into something more readable (at least for someone familiar with streams and lambdas - you don't have to be guru :D )
public static String joinWithourEmptyOrNull(String delimiter, String... words) {
return Arrays.stream(words)
.filter(s -> !StringUtils.isBlank(s))
.collect(Collectors.joining(delimiter));
}
Demo:
System.out.println(joinWithourEmptyOrNull(", ", "firstName", null, " ",
"secondName"));
result firstName, secondName
A simple "fix" would be
String toPrint = "";
if(lastName.length() > 0 && firstName.length() > 0){
toPrint = lastName + ", " - firstName;
}else if(!lastName.length() > 0 && firstName.length() > 0){
toPrint = firstName;
}else if(lastName.length() > 0 && !firstName.length() > 0){
toPrint = lastName;
}
System.out.println(toPrint)

Best way to split a string containing question marks and equals

Having an issue where I have a java string:
String aString="name==p==?header=hello?aname=?????lname=lastname";
I need to split on question marks followed by equals.
The result should be key/value pairs:
name = "=p=="
header = "hello"
aname = "????"
lname = "lastname"
The problem is aname and lname become:
name = ""
lname = "????lname=lastname"
My code simply splits by doing aString.split("\\?",2)
which will return 2 strings.One contains a key/value pair and the second string contains
the rest of the string. If I find a question mark in the string, I recurse on the second string to further break it down.
private String split(String aString)
{
System.out.println("Split: " + aString);
String[] vals = aString.split("\\?",2);
System.out.println(" - Found: " + vals.length);
for ( int c = 0;c<vals.length;c++ )
{
System.out.println(" - "+ c + "| String: [" + vals[c] + "]" );
if(vals[c].indexOf("?") > 0 )
{
split(vals[c]);
}
}
return ""; // For now return nothing...
}
Any ideas how I could allow a name of ?
Disclaimer: Yes , My Regex skills are very low, so I don't know if this could be done via a regex expression.
You can let regex do all the heavy lifting, first splitting your string up into pairs:
String[] pairs = aString.split("\\?(?!\\?)");
That regex means "a ? not followed by a ?", which gives:
[name==p==, header=hello, aname=????, lname=lastname]
To then also split the results into name/value, split only the first "=":
String[] split = pair.split("=", 2); // max 2 parts
Putting it all together:
String aString = "name==p==?header=hello?aname=?????lname=lastname";
for (String pair : aString.split("\\?(?!\\?)")) {
String[] split = pair.split("=", 2);
System.out.println(split[0] + " is " + split[1]);
}
Output:
name is =p==
header is hello
aname is ????
lname is lastname
You can try like this
String[] vals = "Hello??Man?HowAreYou????".split("\\?+");
System.out.println(vals[0]+vals[1]+vals[2]);
OUTPUT
HelloManHowAreYou
But as aname=????? you want to get you can replace the
????? Five Question Marks with Other Symbol and replace back to ????? after split
String processed="Hello????Good? ? ....???".replace("????","*");
OUTPUT
Hello*Good? ? ....???
And than use split for ?
Here the code, you are looking .
Implemented using the Split and HashMap.
Tested and Executed.
import java.util.HashMap;
import java.util.Map;
public class Sample {
public static void main(String[] args) {
// TODO Auto-generated method stub
// String[] vals = "Hello??Man?HowAreYou????".split("\\?+");
// System.out.println(vals[0]+vals[1]+vals[2]);
String query="name==p==?header=hello?aname=?????lname=lastname";
String[] params = query.split("\\?");
Map<String, String> map = new HashMap<String, String>();
for (String param : params)
{
String name = param.split("=")[0];
String value = param.substring(name.length(),param.length());
map.put(name, value);
System.out.println(name);
if(name.equals("")){
value+="?";
}
System.out.println(value.replaceAll(" ", ""));
}
}
}
I assume you are parsing URLs. The correct way would be to encode all special characters like ?, & and = which are values or names.
Better Solution: Encoding characters:
String name = "=p==";
String aname = "aname=????";
String lname = "lastname";
String url = "name=" + URLEncoder.encode(name, "UTF-8") +
"?aname=" + URLEncoder.encode(aname, "UTF-8") +
"?lname=" + URLEncoder.encode(lname, "UTF-8");
After that you have something like this:
name==p==?aname=?????lname=lastname
This can be splitted and decoded easily.
Other Solution: Bad input parsing:
If you insist, this works also. You can use a regex:
Pattern pattern = Pattern.compile("(\\w+?)=(\\S+?\\?+)");
Matcher m = pattern.matcher(query + "?");
while (m.find()) {
String key = m.group(1);
String value = m.group(2);
value = value.substring(0, value.length() - 1);
System.out.println(key + " = " +value);
}

Filter words from string

I want to filter a string.
Basically when someone types a message, I want certain words to be filtered out, like this:
User types: hey guys lol omg -omg mkdj*Omg*ndid
I want the filter to run and:
Output: hey guys lol - mkdjndid
And I need the filtered words to be loaded from an ArrayList that contains several words to filter out. Now at the moment I am doing if(message.contains(omg)) but that doesn't work if someone types zomg or -omg or similar.
Use replaceAll with a regex built from the bad word:
message = message.replaceAll("(?i)\\b[^\\w -]*" + badWord + "[^\\w -]*\\b", "");
This passes your test case:
public static void main( String[] args ) {
List<String> badWords = Arrays.asList( "omg", "black", "white" );
String message = "hey guys lol omg -omg mkdj*Omg*ndid";
for ( String badWord : badWords ) {
message = message.replaceAll("(?i)\\b[^\\w -]*" + badWord + "[^\\w -]*\\b", "");
}
System.out.println( message );
}
try:
input.replaceAll("(\\*?)[oO][mM][gG](\\*?)", "").split(" ")
Dave gave you the answer already, but I will emphasize the statement here. You will face a problem if you implement your algorithm with a simple for-loop that just replaces the occurrence of the filtered word. As an example, if you filter the word ass in the word 'classic' and replace it with 'butt', the resultant word will be 'clbuttic' which doesn't make any sense. Thus, I would suggest using a word list,like the ones stored in Linux under /usr/share/dict/ directory, to check if the word is valid or it needs filtering.
I don't quite get what you are trying to do.
I ran into this same problem and solved it in the following way:
1) Have a google spreadsheet with all words that I want to filter out
2) Directly download the google spreadsheet into my code with the loadConfigs method (see below)
3) Replace all l33tsp33k characters with their respective alphabet letter
4) Replace all special characters but letters from the sentence
5) Run an algorithm that checks all the possible combinations of words within a string against the list efficiently, note that this part is key - you don't want to loop over your ENTIRE list every time to see if your word is in the list. In my case, I found every combination within the string input and checked it against a hashmap (O(1) runtime). This way the runtime grows relatively to the string input, not the list input.
6) Check if the word is not used in combination with a good word (e.g. bass contains *ss). This is also loaded through the spreadsheet
6) In our case we are also posting the filtered words to Slack, but you can remove that line obviously.
We are using this in our own games and it's working like a charm. Hope you guys enjoy.
https://pimdewitte.me/2016/05/28/filtering-combinations-of-bad-words-out-of-string-inputs/
public static HashMap<String, String[]> words = new HashMap<String, String[]>();
public static void loadConfigs() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(new URL("https://docs.google.com/spreadsheets/d/1hIEi2YG3ydav1E06Bzf2mQbGZ12kh2fe4ISgLg_UBuM/export?format=csv").openConnection().getInputStream()));
String line = "";
int counter = 0;
while((line = reader.readLine()) != null) {
counter++;
String[] content = null;
try {
content = line.split(",");
if(content.length == 0) {
continue;
}
String word = content[0];
String[] ignore_in_combination_with_words = new String[]{};
if(content.length > 1) {
ignore_in_combination_with_words = content[1].split("_");
}
words.put(word.replaceAll(" ", ""), ignore_in_combination_with_words);
} catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("Loaded " + counter + " words to filter out");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Iterates over a String input and checks whether a cuss word was found in a list, then checks if the word should be ignored (e.g. bass contains the word *ss).
* #param input
* #return
*/
public static ArrayList<String> badWordsFound(String input) {
if(input == null) {
return new ArrayList<>();
}
// remove leetspeak
input = input.replaceAll("1","i");
input = input.replaceAll("!","i");
input = input.replaceAll("3","e");
input = input.replaceAll("4","a");
input = input.replaceAll("#","a");
input = input.replaceAll("5","s");
input = input.replaceAll("7","t");
input = input.replaceAll("0","o");
ArrayList<String> badWords = new ArrayList<>();
input = input.toLowerCase().replaceAll("[^a-zA-Z]", "");
for(int i = 0; i < input.length(); i++) {
for(int fromIOffset = 1; fromIOffset < (input.length()+1 - i); fromIOffset++) {
String wordToCheck = input.substring(i, i + fromIOffset);
if(words.containsKey(wordToCheck)) {
// for example, if you want to say the word bass, that should be possible.
String[] ignoreCheck = words.get(wordToCheck);
boolean ignore = false;
for(int s = 0; s < ignoreCheck.length; s++ ) {
if(input.contains(ignoreCheck[s])) {
ignore = true;
break;
}
}
if(!ignore) {
badWords.add(wordToCheck);
}
}
}
}
for(String s: badWords) {
Server.getSlackManager().queue(s + " qualified as a bad word in a username");
}
return badWords;
}

Android - Editing my String so each word starts with a capital

I was wondering if someone could provide me some code or point me towards a tutrial which explain how I can convert my string so that each word begins with a capital.
I would also like to convert a different string in italics.
Basically, what my app is doing is getting data from several EditText boxes and then on a button click is being pushed onto the next page via intent and being concatenated into 1 paragraph. Therefore, I assume I need to edit my string on the intial page and make sure it is passed through in the same format.
Thanks in advance
You can use Apache StringUtils. The capitalize method will do the work.
For eg:
WordUtils.capitalize("i am FINE") = "I Am FINE"
or
WordUtils.capitalizeFully("i am FINE") = "I Am Fine"
Here is a simple function
public static String capEachWord(String source){
String result = "";
String[] splitString = source.split(" ");
for(String target : splitString){
result
+= Character.toUpperCase(target.charAt(0))
+ target.substring(1) + " ";
}
return result.trim();
}
The easiest way to do this is using simple Java built-in functions.
Try something like the following (method names may not be exactly right, doing it off the top of my head):
String label = Capitalize("this is my test string");
public String Capitalize(String testString)
{
String[] brokenString = testString.split(" ");
String newString = "";
for(String s : brokenString)
{
s.charAt(0) = s.charAt(0).toUpper();
newString += s + " ";
}
return newString;
}
Give this a try, let me know if it works for you.
Just add android:inputType="textCapWords" to your EditText in layout xml. This wll make all the words start with the Caps letter.
Strings are immutable in Java, and String.charAt returns a value, not a reference that you can set (like in C++). Pheonixblade9's will not compile. This does what Pheonixblade9 suggests, except it compiles.
public String capitalize(String testString) {
String[] brokenString = testString.split(" ");
String newString = "";
for (String s : brokenString) {
char[] chars = s.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
newString = newString + new String(chars) + " ";
}
//the trim removes trailing whitespace
return newString.trim();
}
String source = "hello good old world";
StringBuilder res = new StringBuilder();
String[] strArr = source.split(" ");
for (String str : strArr) {
char[] stringArray = str.trim().toCharArray();
stringArray[0] = Character.toUpperCase(stringArray[0]);
str = new String(stringArray);
res.append(str).append(" ");
}
System.out.print("Result: " + res.toString().trim());

How can you parse the string which has a text qualifier

How can I parse a String str = "abc, \"def,ghi\"";
such that I get the output as
String[] strs = {"abc", "\"def,ghi\""}
i.e. an array of length 2.
Should I use regular expression or Is there any method in java api or anyother opensource
project which let me do this?
Edited
To give context about the problem, I am reading a text file which has a list of records one on each line. Each record has list of fields separated by delimiter(comma or semi-colon). Now I have a requirement where I have to support text qualifier some thing excel or open office supports. Suppose I have record
abc, "def,ghi"
In this , is my delimiter and " is my text qualifier such that when I parse this string I should get two fields abc and def,ghi not {abc,def,ghi}
Hope this clears my requirement.
Thanks
Shekhar
The basic algorithm is not too complicated:
public static List<String> customSplit(String input) {
List<String> elements = new ArrayList<String>();
StringBuilder elementBuilder = new StringBuilder();
boolean isQuoted = false;
for (char c : input.toCharArray()) {
if (c == '\"') {
isQuoted = !isQuoted;
// continue; // changed according to the OP comment - \" shall not be skipped
}
if (c == ',' && !isQuoted) {
elements.add(elementBuilder.toString().trim());
elementBuilder = new StringBuilder();
continue;
}
elementBuilder.append(c);
}
elements.add(elementBuilder.toString().trim());
return elements;
}
This question seems appropriate: Split a string ignoring quoted sections
Along that line, http://opencsv.sourceforge.net/ seems appropriate.
Try this -
String str = "abc, \"def,ghi\"";
String regex = "([,]) | (^[\"\\w*,\\w*\"])";
for(String s : str.split(regex)){
System.out.println(s);
}
Try:
List<String> res = new LinkedList<String>();
String[] chunks = str.split("\\\"");
if (chunks.length % 2 == 0) {
// Mismatched escaped quotes!
}
for (int i = 0; i < chunks.length; i++) {
if (i % 2 == 1) {
res.addAll(Array.asList(chunks[i].split(",")));
} else {
res.add(chunks[i]);
}
}
This will only split up the portions that are not between escaped quotes.
Call trim() if you want to get rid of the whitespace.

Categories