Trying to alternate two strings together in Java - java

/* Programs goal is to take two strings and use a method to alternate the characters.
example - "test" "case" -> "tceasste"
Sorry I tried looking at other similar questions but I didn't understand how they worked as I am very new to Java and coding in general.
*/
public class MyProgram extends ConsoleProgram
{
public void run()
{
System.out.println(sCombine("test","case")); //"tceasste"
System.out.println(sCombine("avalanche","dog")); //"advoaglanche"
System.out.println(sCombine("","water")); //"water"
}
public String sCombine(String a, String b)
{
String result = "";
int lengtha = a.length();
int lengthb = b.length();
int lengthc = 0;
if(lengtha < lengthb)
{
lengthc = lengtha;
}
else
{
lengthc = lengthb;
}
for(int i = 0; i < lengthc; i++)
{
char currentA = a.charAt(i);
char currentB = b.charAt(i);
result += a;
result += b;
}
return result;
}
}

The problem is that you're doing:
result += a;
You need to do:
result += currentA;
I would also suggest looking at the StringBuilder class. It has a lot of built in functionality for things of this nature :)

Just another way. Read all the comments in code:
/**
* Sequentially blends two strings together one character at a time, for
* example, if the first argument was "cat" and the second argument was
* "dog" then the returned result will be: "cdaotg".<br><br>
*
* <b>Example Usage:</b><pre>
* {#code
* final String a = "cat";
* final String b = "elephant";
* String newString = sCombine(a, b);
* System.out.println(newString);
* // Console will display: cealte }
*
* OR
* {#code
* final String a = "cat";
* final String b = "elephant";
* String newString = sCombine(a, b, true); // true is optionally supplied here.
* System.out.println(newString);
* // Console will display: eclaetphant }</pre>
*
* #param stringA (String) The first String to blend.<br>
*
* #param stringB (String) The second String to blend.<br>
*
* #param startWithLongest (Optional - boolean varArgs) Default is false <pre>
* whereas this method will always take the first
* supplied argument and blend the second argument
* into it. In this default situation, the first
* argument is always considered to contain the
* longest String. If however, the second argument
* contains more characters then the those extra
* characters will be truncated, for example: "cat"
* and "elephant". Result will be: "cealte". It would
* be beneficial to always pass the longest string as
* the first argument in order to achieve the result
* of: "eclaetphant".
*
* If boolean true is supplied to this optional parameter
* then the longest argument passed to this method will
* always be considered as the first argument rather than
* the first supplied argument, for example: "cat" as the
* first argument and "elephant" as the second argument
* and true as the third argument will return a result
* of "eclaetphant".
*
* Supplying nothing forces default to be used.</pre>
*
* #return (String) The blended String;
*/
public static String sCombine(final String stringA, final String stringB,
final boolean... startWithLongest) {
String strgA = stringA, strgB = stringB; // So to maintain original Strings
/* If `true` is supplied to the startWithLongest optional
vararg parameter then ensure the String argument with the
most characters is the first argument (if true, always place
the longest first). */
if (startWithLongest.length > 0 && startWithLongest[0]) {
if (strgB.length() > strgA.length()) {
strgA = stringB;
strgB = stringA;
}
}
// Build the new blended string
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < strgA.length(); i++) {
sb.append(strgA.charAt(i))
/* 'Ternary Operator' is used here to ensure strgB
contains the current index to carry on. If not
then just the remaining characters of strgA are
sequentially apended to the StringBuilder object
to finish up things. */
.append(i < strgB.length() ? strgB.charAt(i) : "");
}
return sb.toString();
}

You can use a loop that iterates the maximum length of both the strings. Then you can extract the individual character at the ith position and add it alternatively to a resulting String object. I have used StringBuiler as it mutable( diff here ) This is the code that I have attached.
public class MyProgram {
public static void main(String[] args) {
System.out.println(sCombine("test", "case")); // "tceasste"
System.out.println(sCombine("avalanche", "dog")); // "advoaglanche"
System.out.println(sCombine("", "water")); // "water"
}
public static String sCombine(String a, String b) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < Math.max(a.length(), b.length()); i++) {
char aChar = i < a.length() ? a.charAt(i) : '#';
char bChar = i < b.length() ? b.charAt(i) : '#';
if (aChar != '#') {
result.append(aChar + "");
}
if (bChar != '#') {
result.append(bChar + "");
}
}
return result.toString();
}
}
and the output is :
tceasste
advoaglanche
water

You can use substring to savely append the remainder of the Strings. Should the limit be out of bounds, no exception will be thrown, because substring will just return an empty String.
public String sCombine(String a, String b) {
final StringBuilder builder = new StringBuilder();
final int min = Math.min(a.length(), b.length());
for (int i = 0; i < min; i++) {
builder.append(a.charAt(i)).append(b.charAt(i));
}
builder.append(a.substring(min)).append(b.substring(min));
return builder.toString();
}

take two strings and use a method to alternate the characters.
example - "test" "case" -> "tceasste"
private static String mixedUp(String first, String second)
{
First, identify the shorter string so it won't attempt to pull a character that is out out bounds
int length = (first.length() > second.length())
? second.length() : first.length();
Then for that length, add their alternating characters to a new String() Object like so:
String output = new String();
for(int index = 0; index < length; index++)
{
output += first.charAt(index);
output += second.charAt(index);
}
You can use substring to savely append the remainder of the Strings. Should the limit be out of bounds, no exception will be thrown, because substring will just return an empty String. - #thinkgruen
You can add the rest of the characters using the ternary operator again like so:
output += (first.length() > second.length())
? second.substring(length) : first.substring(length);
return output;
}

Related

returning string containing char c in scanner

Trying to create a method findNewLineWithChar() which returns a String and accepts a Scanner scn and a char c. It returns the line of the scanner which contains c.
I've tried using a string to store the value of currentLine, but it seemed to convolute my code and not provide any answers anyways. I would love to use a String[], but I get a NullPointerException. What am I exactly doing wrong?
public static String findLineWithChar(Scanner scn, char c) {
/*
* findLineWithChar returns line in scanner if line has char c
* #param scanner
* #param c
*/
String result = "";
String[] stringArray = new String[10]; //accepts max 10 lines
int counter = 0; //populate string array from scn
while(scn.hasNextLine()) {
stringArray[counter] = scn.nextLine();
counter++;
}
//iterate through each element in string array
for (int i = 0; i < 10; i++) {
if (stringArray[i].contains(c + "")) {
result = stringArray[i];
System.out.println(stringArray[i]);
break;
} else {
result = "";
}
}
return result;
}
It works if I feed it a true statement,
findLineWithChar(new Scanner("Look here!\nLook there!\nExtra extra!"), 'x') returns Extra extra!, but findLineWithChar(new Scanner("Look here!\nLook there!\nExtra extra!"), 'q') returns a NullPointerException. How do I deal with this?
First, Javadoc comments go before the method (and start with /**). Second, you don't need an array here; just keep a count to make sure you don't consume more than ten lines (assuming that's necessary). Instead of setting a return variable and breaking the loop, I would return when a matching line is found. I would also prefer String.indexOf(int) to building one character String(s) for comparison. And, add a default return value for when nothing matches. Like,
/**
* findLineWithChar returns line in scanner if line has char c
*
* #param scanner
*
* #param c
*/
public static String findLineWithChar(Scanner scn, char c) {
int counter = 0;
while (scn.hasNextLine() && counter < 10) {
String line = scn.nextLine();
if (line.indexOf(c) > -1) {
return line;
}
counter++;
}
return "";
}
You almost got it! Just change condition of your while loop.
from this:
while(scn.hasNextLine()) {
to this:
while(scn.hasNextLine() && counter < 10) {

Need to encode repetitive pattern in String with * , such that * means "repeat from beginning"

Encoding format: introduce * to indicate "repeat from beginning". Example. Input-{a,b,a,b,c,a,b,a,b,c,d} can be written as {a , b, * ,c, * , d}. Output:5; E.g 2: ABCABCE, output- 5.
Here * means repeat from beginning. For example if given String is ABCABCABCABC , it will return ABC**, another example is if String is ABCABCABC, it will return ABC*ABC.
I have the below code but this code assumes that the string will contain the repetitive pattern only and no other characters, I want to modify it to check :
1. Which pattern is repeating
2. Ignore non repeating patterns
2. encode that pattern according to the problem statement
import java.util.Scanner;
public class Magicpotion {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the string:");
String str = sc.nextLine();
int len = str.length();
if (len != 0) {
int lenby3 = len / 3;
int starcount = ( int).(Math.log(lenby3) / Math.log(2));
int leftstring = (lenby3 - (int) Math.pow(2, starcount));
int resultlen = (1 * 3) + starcount + (leftstring * 3);
System.out.println("ResultLength: " + resultlen);
System.out.print("ABC");
for (int i = 0; i < starcount; i++) {
System.out.print("*");
}
for (int i = 0; i < leftstring; i++) {
System.out.print("ABC");
}
} else
System.out.println("ResultLength: " + 0);
}
}
Here my assumption is that ABC will always be repeating pattern , hence I have divided the length by 3. I want to generalise it such that I find the repeating pattern which can be a AB or BC or ABCD and proceed accordingly.
This looks like homework. So instead of a full solution just some hints:
You can process the input string character by character and encode as you go. If you have at some point already read k characters and the next k characters are exactly the same, output a * and advance to position 2k.
Otherwise, output the next input character and advance position to k+1.
As mentioned by dyukha this algorithm does not always result in the shortest possible encoding. If this is required some more effort has to be put into the search.
This problem can be solved using dynamic programming.
Assume that you processed your stay at some position i. You want to understand what it the minimal length of encoding of str[0..i]. Let's call it ans[i]. You have two options:
Just add i-th character to the encoding. So the length is ans[i-1] + 1.
You may write *, when possible. In this case the length is ans[i / 2] + 1 or something like this.
The final length is in ans[n-1]. You can store how you obtained ans[i] to recover the encoding itself.
Checking whether you can write * can be optimized, using some hashing (to obtain O(n) solution instead of O(n^2)).
The difference with Henry's solution is that he always applies * when it's possible. It's not clear to me that it results into the minimal length (if I understood correctly, aaaaaa is a counterexample), so I'm giving a solution I'm sure about.
/**
* #author mohamed ali
* https://www.linkedin.com/in/oo0shaheen0oo/
*/
public class Magic_potion_encoding
{
private static int minimalSteps( String ingredients )
{
StringBuilder sb = new StringBuilder(ingredients);
for(int i =0;i<sb.length();i++)
{
char startChar = sb.charAt(i);
int walkingIndex1=i;
int startIndex2 =sb.toString().indexOf(startChar,i+1);
int walkingIndex2=startIndex2;
while(walkingIndex2 !=-1 && walkingIndex2<sb.length() && sb.charAt(walkingIndex1) == sb.charAt(walkingIndex2) )
{
if(walkingIndex1+1==startIndex2)
{
String subStringToBeEncoded = sb.substring(i,walkingIndex2+1);//substring the string found and the original "substring does not include the last index hence the +1
int matchStartIndex = sb.indexOf(subStringToBeEncoded,walkingIndex2+1);// look for first match for the whole string matched
int matchEndeIndex= matchStartIndex+subStringToBeEncoded.length();
int origStartIndex=i;
int origEndIndex = i+subStringToBeEncoded.length();
if (matchStartIndex!=-1 )
{
if(origEndIndex==matchStartIndex)
{
sb.replace(matchStartIndex,matchEndeIndex,"*");
}
else
{
while(matchStartIndex!=-1 && matchEndeIndex<sb.length() && sb.charAt(origEndIndex) == sb.charAt(matchEndeIndex) )
{
if(origEndIndex==matchStartIndex-1)// if the index of the 2 strings are right behind one another
{
sb.replace(matchStartIndex,matchEndeIndex+1,"*");
}
else
{
origEndIndex++;
matchEndeIndex++;
}
}
}
}
sb.replace(startIndex2,walkingIndex2+1,"*");
break;
}
walkingIndex1++;
walkingIndex2++;
}
}
System.out.println("orig= " + ingredients + " encoded = " + sb);
return sb.length();
}
public static void main( String[] args )
{
if ( minimalSteps("ABCABCE") == 5 &&
minimalSteps("ABCABCEA") == 6 &&
minimalSteps("abbbbabbbb") == 5 &&
minimalSteps("abcde") == 5 &&
minimalSteps("abcbcbcbcd") == 6 &&
minimalSteps("ababcababce") == 6 &&
minimalSteps("ababababxx") == 6 &&
minimalSteps("aabbccbbccaabbccbbcc") == 8)
{
System.out.println( "Pass" );
}
else
{
System.out.println( "Fail" );
}
}
}
Given that the repetitions are from the beginning, every such repeating substring will have the very first character of the given string. [Every repetition needs to be represented by a "star". (i.e ABCABCABC ans = ABC** ) . If all sequential repetitions are to be represented with one "star". (i.e ABCABCABC and = ABC* ), a slight modification to (2) will do the thing (i.e remove the if case where the just a star is added)]
Divide the given string to substrings based on the first character.
Eg. Given String = "ABABCABD"
Sub Strings = {"AB", "ABC", "AB", "ABD"}
Just traverse through the list of substrings and get the required result. I've used a map here, to make the search easy.
Just a rough write up.
SS = {"AB", "ABC", "AB", "ABD"};
result = SS[0];
Map<string, bool> map;
map.put(SS[0],true);
for (i = 1; i < SS.length; i++){
if (map.hasKey(SS[i])){
result += "*";
}
else {
res = nonRepeatingPart(SS[i], map);
result += "*" + res;
map.put(SS[i], true);
}
}
String nonRepeatingPart(str, map){
for (j = str.length-1; j >= 0; j--){
if (map.hasKey(str.subString(0, j))){
return str.subString(j, str.length-1);
}
}
return throwException("Wrong Input");
}
string getCompressed(string str){
string res;
res += str[0];
int i=1;
while(i<str.size()){
//check if current char is the first char in res
char curr = str[i];
if(res[0]==curr){
if(str.substr(0,i)==str.substr(i,i)){
res += '*';
i+=i; continue;
}else{
res += curr;
i++; continue;
}
}else {
res += curr;
i++; continue;
}
}
return res;
}
int main()
{
string s = "ABCABCABC";
string res = getCompressed(s);
cout<<res.size();
return 0;
}

Java Loops -- Strings of First and last characters of every word

I am currently in an Intro to Programming class at San Jose and as part of our assignment we were to create a class with methods that either return a string with the first letters of each word or the last letters of each word.
The instance variable "phrase" holds the phrase that is accessed in the methods.
Here are the rules:
The words are separated by spaces,
It starts with a letter,
It does not end with a space,
There are never 2 consecutive spaces,
There are never 2 consecutive digits or punctuation.
Both the firstLetter() and lastLetter() methods must return an empty string if the phrase is empty.
My question is: What is a more efficient solution to this problem? I am new to algorithms so I would appreciate a more seasoned approach to this simple problem. In the firstLetter() and the lastLetter() method, would I check the status of two characters at a time within the for loop or just one?
Here is my code:
/**
* Processes first and last letters of words
* #author (Adrian DeRose)
*/
public class StartToFinish
{
private String phrase;
/**
* Constructs a StartToFinish object
* #param myString the phase for this object
*/
public StartToFinish(String myString)
{
this.phrase = myString;
}
/**
* Gets first letter of every word in string.
*
* #return first letter of every word in string
*/
public String firstLetters()
{
String firstLetters = "";
if (Character.isLetter(this.phrase.charAt(0)))
{
firstLetters += this.phrase.substring(0,1);
}
for (int i = 1; i < this.phrase.length(); i++)
{
char currentCharacter = this.phrase.charAt(i);
String previousCharacter = Character.toString(this.phrase.charAt(i-1));
if (Character.isLetter(currentCharacter) && previousCharacter.equals(" "))
{
String characterString = Character.toString(currentCharacter);
firstLetters += characterString;
}
}
return firstLetters;
}
/**
* Gets last letter of every word in string.
*
* #return last letter of every word in string
*/
public String lastLetters()
{
String lastLetters = "";
char lastCharacter = this.phrase.charAt(lastIndex);
if (this.phrase.length() == 0)
{
return "";
}
for (int i = 1; i < this.phrase.length(); i++)
{
char currentCharacter = this.phrase.charAt(i);
char previousCharacter = this.phrase.charAt(i-1);
if (Character.isLetter(previousCharacter) && !Character.isLetter(currentCharacter))
{
String previousCharacterString = Character.toString(previousCharacter);
lastLetters += previousCharacterString;
}
}
if (Character.isLetter(lastCharacter))
{
lastLetters += Character.toString(lastCharacter);
}
return lastLetters;
}
}
Thank you!
i don't know if this is what you are looking for, but this is much more simple way to write the same (sorry for my English)
String a="john snow winter is comming";
String[] parts = a.split(" ");
for(String word:parts){
System.out.println("first letter "+word.charAt(0)+ " last letter "+word.charAt(word.length()-1));
}
I don't think so you have to write all those code just use java function:
String a = "Hello";
System.out.println("First:"+a.charAt(0));
System.out.println("Last:"+a.charAt(a.length()-1));
Output:
First:H
Last:o
One of the solution I will provide is :
1. Check if the phrase is empty in the constructor.
2. Begin with a split, and then do some check.
In the constructor (This isn't needed in your case btw)
splitedPhrase = phrase.split(' ');
In the dedicated function
public String firstLetters() {
String result = "";
for(String word : splitedPhrase) {
if (Character.isLetter(word.charAt(0)))
result+=word.charAt(0);
}
return result;
}
And you just have to change the charAt for the LastLetter function, like
word.charAt(word.length-1)
Hope this help, despite some people already posted, I think this will better do what your algortihm need.
If I understand your question correctly, I think this is what you're looking for:-
public class StartToFinish {
private String phrase;
private String[] words;
private String firstLetters = "";
private String lastLetters = "";
/**
* Constructs a StartToFinish object
*
* #param myString
* the phase for this object
*/
public StartToFinish(String myString) {
this.phrase = myString;
words = phrase.split(" ");
for (String string : words) {
if (string.length() == 0)
continue;
if (Character.isLetter(string.charAt(0))) {
firstLetters += string.charAt(0);
}
if (Character.isLetter(string.charAt(string.length() - 1))) {
lastLetters += string.charAt(string.length() - 1);
}
}
}
/**
* Gets first letter of every word in string.
*
* #return first letter of every word in string
*/
public String firstLetters() {
return firstLetters;
}
/**
* Gets last letter of every word in string.
*
* #return last letter of every word in string
*/
public String lastLetters() {
return lastLetters;
}
}

Divide two String into substrings and pair them

I am looking for interesting solutions for this problem :
String key = "1;2;3;4";
String value = "Value1;Value2;Value whitespace;"
Now ';' devides each value from another. The same symbol ';' devides the keys also.
Now I want to end up with :
{"1" : "Value1", "2" : "Value2", "3" : "Value whitespace", "4" : null}
Of course if the values were more then the keys then the null should be no the left side of the pair (null: "Value5").
I made a pretty complecated solution to this problem using char arrays but is one big FOR with many cases and stuff.(it is O(n)). So I am curious to see a regex or substring solution or something that not includes big loop.
EDIT:
Mine solution :
private List<ExampleObject> getExampleObjects(String key , String value) {
// s
if (key == null || value == null) {
return new ArrayList<ExampleObject>();
}
List<ExampleObject> exampleObjects = new ArrayList<ExampleObject>();
char[] keyToCharArray = key.toCharArray();
char[] valueToCharArray = value.toCharArray();
StringBuilder name = new StringBuilder();
StringBuilder value = new StringBuilder();
boolean nameCompleted = false;
boolean valueCompleted = false;
for (int i = 0, j = 0; i < keyToCharArray.length || j < valueToCharArray.length;) {
if (!nameCompleted) {
char a = ' ';
try{
a = keyToCharArray[i];
} catch(Exception e){
a = ';';
// throw : VALES and key not match. More key then value
//throw(e);
}
if (a == ';' ) {
nameCompleted = true;
} else if (!(i + 1 < keyToCharArray.length)){
name.append(a);
nameCompleted = true;
} else {
name.append(a);
}
i++;
}
if (!valueCompleted) {
char a = ' ';
try{
a = valueToCharArray[j];
} catch(Exception e){
a = ';';
// throw : VALES and key not match. More value then key
//throw(e);
}
if (a == ';') {
valueCompleted = true;
} else if(!(j + 1 < valueToCharArray.length)) {
value.append(a);
valueCompleted = true;
} else {
value.append(a);
}
j++;
}
if (nameCompleted && valueCompleted) {
exampleObjects.add(new ExampleObject(name.toString(), value.toString()));
name.setLength(0);
value.setLength(0);
nameCompleted = false;
valueCompleted = false;
}
}
return exampleObjects;
}
Where ExampleObject.class has fields key and value.
I've come up with a solution to your problem:
Output
{"1" : "Value1", "2" : "Value2", "3" : "Value whitespace", "4" : "null"}
Code
public class HelloWorld{
public static void main(String []args){
String key = "1;2;3;4";
String value = "Value1;Value2;Value whitespace;";
String[] keyArr = key.split(";");
String[] valueArr = value.split(";");
String finalJSON = "{";
for(int i=0; i<(keyArr.length > valueArr.length ? keyArr.length : valueArr.length); i++) {
try {
finalJSON += "\"" + keyArr[i] + "\"";
}
catch(ArrayIndexOutOfBoundsException e) {
finalJSON += "\"null\"";
}
finalJSON += " : ";
try {
finalJSON += "\"" + valueArr[i] + "\"";
}
catch(ArrayIndexOutOfBoundsException e) {
finalJSON += "\"null\"";
}
if(i!=(keyArr.length > valueArr.length ? keyArr.length : valueArr.length) - 1)
finalJSON += ", ";
}
finalJSON += "}";
System.out.println(finalJSON);
}
}
Java 8:
String key = "1;2;3;4";
String value = "Value1;Value2;Value whitespace;";
String[] keys = key.split(";", -2);
String[] values = value.split(";", -2);
Map<String, String> result = IntStream.range(0, keys.length).mapToObj(i->i).collect(Collectors.toMap(i->keys[i], i-> values[i]));
result.entrySet().forEach(e->result.put(e.getKey(), e.getValue().length()==0 ? null : e.getValue()));
Another - slightly more elegant Java8 and Generic as possible.
/**
* General pair of items.
*
* #param <P> - Type of the first item in the pair.
* #param <Q> - Type of the second item.
*/
static class Pair<P, Q> {
final P p;
final Q q;
public Pair(P p, Q q) {
this.p = p;
this.q = q;
}
#Override
public String toString() {
return "{" + p + "," + q + "}";
}
}
/**
* Gets the `n`th item is present in the array - otherwise returns null.
*
* #param a - The array
* #param n - Which one in the array we want.
* #param <T> - The type of the array entries.
* #return - The `n`th entry in the array or null if not present.
*/
private static <T> T n(T[] a, int n) {
return n < a.length ? a[n] : null;
}
/**
* Pairs up each element in the arrays.
*
* #param <P> - The type of the elements in the `P` array.
* #param <Q> - The type of the elements in the `Q` array.
* #param ps - The `P` array.
* #param qs - The `Q` array.
* #return A list of `Pair`s of each element.
*/
static <P, Q> List pairUp(P[] ps, Q[] qs) {
return IntStream.range(0, Math.max(ps.length, qs.length))
.mapToObj(i -> new Pair<>(n(ps, i), n(qs, i)))
.collect(Collectors.toList());
}
/**
* Splits the two strings on a separator and returns a list of Pairs of the corresponding items.
*
* #param a - The first string.
* #param b - The second string.
* #param separator - The separator.
* #return - A List of Paired up entries from `a` and `b`.
*/
private static List<Pair<String, String>> fold(String a, String b, String separator) {
return pairUp(a.split(separator, -1), b.split(separator, -1));
}
public void test() {
System.out.println(fold("1;2;3;4", "Value1;Value2;Value whitespace", ";"));
}
Try the following: (if you want to print a String as you said)
Split the two Strings into Arrays using String#split()
Create counters for the value[] and the key[]
Create a boolean to indicate if a key or a value gets appended
Use a StringBuilder and loop through the length of the key[]
Append stuff
Return a new String using StringBuilder#append()
Done. Try it before checking out the solution!
StringBuilder: https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html
String: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html
My solution for printing out the String:
public static void main(String[] args) {
String key = "1;2;3;4";
String value = "Value1;Value2;Value whitespace";
String[] keys = key.split(";");
String[] values = value.split(";");
StringBuilder sb = new StringBuilder("{");
boolean isKey = true;
int keyCount = 0;
int valueCount = 0;
for(int i = 0; i < key.length(); i++) {
sb.append("\"");
if(isKey) {
sb.append(keys[keyCount]).append("\" : ");
keyCount++;
} else {
sb.append(values[valueCount]).append("\", ");
valueCount++;
}
isKey = !isKey;
}
sb.append("}");
System.out.println(sb.toString());
}
A different point of view: don't do such things "manually".
What I mean is: instead of doing all "low level" operations yourself; you should abstract.
First, transform your key value strings into a Map. Like:
String keys[] = keyString.split(";");
String values[] = valueString.split(";);
... probably some consistency checks that arrays have same length; and no nulls in keys
Map<String, String> map = new HashMap<>();
for (int i=0; i < keys.length; i++) {
map.put(keys[i], values[i]);
}
then finally, use some existing JSON library to simply generate a JSON representation based on that map.
In other words: unless you are talking about lists with millions of entries; do not worry about performance. Instead, worry about good abstractions, not re-inventing the wheel and code readability.
But if you really have to worry about performance, or memory aspects, then simply split into arrays, and then use those two arrays as input to some function that uses a StringBuilder to build the required output string.

How to center a string by formatting in Java?

I want my String to be formatted both from the left and right side, so it always keeps standing in the center.
Let's say I want the total length to be 30 symbols (let's mark spaces as stars to see clearly). I want the following result.
sampleString -> *********sampleString*********
sampleLongLongString -> *****sampleLongLongString*****
I tried to do the following.
result = padLeft("", 15) + padRight(myString, 15);
or
result = padLeft(padRight(myString, 15), 15);
For functions,
public static String padRight(String s, int n) {
return String.format("%1$-" + n + "s", s);
}
public static String padLeft(String s, int n) {
return String.format("%1$" + n + "s", s);
}
but no result.
You can create a method to add padding based on the length of the String.
Basically, you have to decide the total/max(left+right) padding for all the Strings. Please take a look at following method.
It also manages the space inside the String. Method will just return actual String if padding can not be added according to maxPadding.
public static String getPaddedString(String str, char paddingChar) {
if (str == null) {
throw new NullPointerException("Can not add padding in null String!");
}
int maxPadding = 20;//This is what you have to decide
int length = str.length();
int padding = (maxPadding - length) / 2;//decide left and right padding
if (padding <= 0) {
return str;// return actual String if padding is less than or equal to 0
}
String empty = "", hash = "#";//hash is used as a place holder
// extra character in case of String with even length
int extra = (length % 2 == 0) ? 1 : 0;
String leftPadding = "%" + padding + "s";
String rightPadding = "%" + (padding - extra) + "s";
String strFormat = leftPadding + "%s" + rightPadding;
String formattedString = String.format(strFormat, empty, hash, empty);
//Replace space with * and hash with provided String
String paddedString = formattedString.replace(' ', paddingChar).replace(hash, str);
return paddedString;
}
Following program proves that above method works,
public class Test {
public static void main(String args[]) {
System.out.println(getPaddedString("Hello", '*'));
System.out.println(getPaddedString("Hi23", '#'));
System.out.println(getPaddedString("Test. .Test", '%'));
System.out.println(getPaddedString(
"By the way, It's to long to fix !!", '*'));
}
}
OUTPUT
************Hello************
#############Hi23############
%%%%%%%%%Test. .Test%%%%%%%%%
By the way, It's to long to fix !!
Here's an easy-to-understand method to do it:
public static String center(String string, int length, char pad) {
StringBuilder sb = new StringBuilder(length);
sb.setLength((length - string.length()) / 2);
sb.append(string);
sb.setLength(length);
return sb.toString().replace('\0', pad);
}
With this code, when the total padding required is odd, the right-side padding has one extra pad char. To change the behaviour so that the left side gets the extra pad, change line 2 to:
sb.setLength((length - string.length() + 1) / 2);
This method will do the trick.
/**
* #param int w : length of the formatted string (e.g. 30)
* #param String s : the string to be formatted
* #param char c : character to pad with
* #param boolean pr: If s is odd, pad one extra left or right
* #return the original string, with pad 'p' on both sides
*/
private String pad(String s, int w, char c, boolean pr){
int pad = w-s.length();
String p = "";
for (int i=0; i<pad/2; i++)
p = p + c;
/* If s.length is odd */
if (pad%2 == 1)
/* Pad one extra either right or left */
if (pr) s = s + c;
else s = c + s;
return (p+s+p)
}

Categories