Java 8: Generating String ID from Long - java

Below is the method I am using to generate a string reference id which is of length 12 and starts with 'X' and ends with the input number and the middle of String is filled with zeros
public String generateRefId(Long number){
int digits = 1 + (int)Math.floor(Math.log10(number));
int length = 11 - digits;
StringBuilder refid = new StringBuilder(12);
refid.append('X');
for(int i= length;i> 0;i--) {
refid.append('0');
}
refid.append(number);
Assert.assertEquals(refid.length(),12);
return refid.toString();
}
Below are the usecases
Input Output
12345 X00000012345
999999999 X00999999999
The above method works fine but Am wondering if the above method can be optimized further using java 8?

You can use String.format. E.g.
String.format("X%011d", 4366)
This pads the number with 0 on the left side. But be aware, that larger numbers, will take more space.
groovy:000> String.format("X%011d", 4366)
===> X00000004366
groovy:000> String.format("X%011d", 111111111111)
===> X111111111111

IFF guava is an option, this would be so much easier:
String input = "12345";
System.out.println("X" + Strings.padStart(input, 11, '0'));

In Groovy, since 1.0:
'X' + input.padLeft(11, '0')

As alternative, apache-commons-lang provides the StringUtils.leftPad() method :
public static String leftPad(final String str, final int size, final char padChar)
You could so write :
String input = "999999999";
String formatedValue = "X" + StringUtils.leftPad(input, 11, '0');

Related

What are some ways to avoid String.substring from returning substring with invalid unicode character?

Recently, only I notice that, it is possible for substring to return string with invalid unicode character.
For instance
public class Main {
public static void main(String[] args) {
String text = "🥦_Salade verte";
/* We should avoid using endIndex = 1, as it will cause an invalid character in the returned substring. */
// 1 : ?
System.out.println("1 : " + text.substring(0, 1));
// 2 : 🥦
System.out.println("2 : " + text.substring(0, 2));
// 3 : 🥦_
System.out.println("3 : " + text.substring(0, 3));
// 4 : 🥦_S
System.out.println("4 : " + text.substring(0, 4));
}
}
I was wondering, when trimming a long string with String.substring, what are some good ways to avoid the returned substring from containing invalid unicode?
char obsolete
The char type has been legacy since Java 2, essentially broken. As a 16-bit value, char is physically incapable of representing most characters.
Your discovery suggests that the String#substring command is char based. Hence the problem shown in your code.
Code point
Instead, use code point integer numbers when working with individual characters.
int[] codePoints = "🥦_Salade".codePoints().toArray() ;
[129382, 95, 83, 97, 108, 97, 100, 101]
Extract the first character’s code point.
int codePoint = codePoints[ 0 ] ;
129382
Make a single-character String object for that code point.
String firstCharacter = Character.toString( codePoint ) ;
🥦
You can grab a subset of that int array of code points.
int[] firstFewCodePoints = Arrays.copyOfRange( codePoints , 0 , 3 ) ;
And make a String object from those code points.
String s =
Arrays
.stream( firstFewCodePoints )
.collect( StringBuilder::new , StringBuilder::appendCodePoint , StringBuilder::append )
.toString();
🥦_S
Or we can use a constructor of String to take a subset of the array.
String result = new String( codePoints , 0 , 3 ) ;
🥦_S
See this code run live at IdeOne.com.
The answer by Basil nicely shows that you should work with code points instead of chars.
A String does not store Unicode code points internally, so there is no way to know which characters belong together forming a Unicode code point, without inspecting the actual contents of the string.
Unicode-aware substring
Here is a Unicode-aware substring method. Since codePoints() returns an IntStream, we can utilize the skip and limit methods to extract a portion of the string.
public static String unicodeSubstring(String string, int beginIndex, int endIndex) {
int length = endIndex - beginIndex;
int[] codePoints = string.codePoints()
.skip(beginIndex)
.limit(length)
.toArray();
return new String(codePoints, 0, codePoints.length);
}
This is what happens in the abovementioned snippet of code. We stream over the Unicode code points, skipping the first beginIndex bytes and limiting the stream to endIndex − beginIndex, and then convertb to int[]. The result is that the int array contains all Unicode code points from beginIndex up to endIndex.
At last, the String class contains a nice constructor to construct a String from an int[] with code points, so we use it to get the String.
Of course, you could tweak the method to be a little more strict by rejecting out-of-bounds values:
if (endIndex < beginIndex) {
throw new IllegalArgumentException("endIndex < beginIndex");
}
int length = endIndex - beginIndex;
int[] codePoints = string.codePoints()
.skip(beginIndex)
.limit(length)
.toArray();
if (codePoints.length < length) {
throw new IllegalArgumentException(
"begin %s, end %s, length %s".formatted(beginIndex, endIndex, codePoints.length)
);
}
return new String(codePoints, 0, codePoints.length);
Online demo
I would like to provide another point of view, on how to implement substring which is able to guarantee the returned string contains valid unicode.
Unlike answer provided by #MC Emperor, my code treats
🥦 length as 2 (Instead of 1 by #MC Emperor)
This is important, to ensure the new function's behavior will resemble as close as old String.substring.
public static int length(String string) {
if (string == null) {
return 0;
}
return string.length();
}
public static String limitLength(String string, int maxLength) {
int stringLength = length(string);
if (stringLength <= maxLength) {
return string;
}
List<Integer> codePointList = new ArrayList<>();
for (int offset = 0; offset < maxLength; ) {
final int codePoint = string.codePointAt(offset);
final int charCount = Character.charCount(codePoint);
if ((offset + charCount) > maxLength) {
break;
}
codePointList.add(codePoint);
offset += charCount;
}
int[] codePoints = new int[codePointList.size()];
for (int i = 0; i < codePoints.length; i++)
{
codePoints[i] = codePointList.get(i);
}
String result = new String(codePoints, 0, Math.min(maxLength, codePoints.length));
return result;
}
The code performance might not be efficient, if the maxLength value is large. But, I can't think of a much better way now. If you know a better way, feel free to amend the answer.
It is by design. Java provides many ways to extract individual Unicode code points from a string if it's necessary: see the Oracle tutorial.
However, most of the time it's not needed since you get the string index from a method like String.indexOf(String s) or Matcher.start(). In this case the resulting index won't point in the middle of a code point (as long as the argument s is a valid Unicode string).
It's even more common to work with regular expressions where string indexes don't come up altogether.

Extracting a char from a string

I need to extract a char from a preset string. I know the method string.charAt(), I use it but it crash my program. The context that I use is the following :
private String values = "0123456789ABCDEFG";
//Converts a 10 base number to a q base
private String t2q(String number, String base) {
String a = Double.toString((int)(Double.parseDouble(number) / Double.parseDouble(base)));
String b = Double.toString((int)(Double.parseDouble(number) % Double.parseDouble(base)));
StringBuilder converted = new StringBuilder(a + b);
if (!check_base(converted.toString(), base)) {
return t2q(a, base) + values.charAt(Integer.parseInt(b));
}
char ab = values.charAt(Integer.parseInt(a));
char ba = values.charAt(Integer.parseInt(b));
return "" + ab + ba;
}
At the beginning i was thinking that my program crash because a is in a Double format e.g 1.0 so i use a function that transforms 1.0 in 1 but nothing, it still crashes. Also i tried with Character instead of char but it doesn't make a difference.
The Exception Error is "java.lang.NumberFormatException: Invalid int : "1.0"" for the example number = "11011" and base = 16 , so 11011 in base 16 is 1B.
You can't parse a String which represents a Double with Integer.parseInt().
This will not work:
Integer.parseInt("3.0");
This will work:
Integer.parseInt("3");
Use this instead:
new Double("3.0").intValue()
But consider following behavior:
new Double("2.5").intValue() will return 2.

Convert String / char into specified-digit binary string and vice versa in java

I'm trying to convert a string (or a single char) into given number of digits binary string in java. Assume that given number is 5, so a string "zx~q" becomes 01101, 10110, 11011, 10011 (I' ve made up the binaries). However, I need to revert these binaries into "abcd" again. If given number changes, the digits (so the binaries) will change.
Anyone has an idea?
PS: Integer.toBinaryString() changes into an 8-digit binary array.
Looks like Integer.toString(int i, int radix) and Integer.parseInt(string s, int radix) would do the trick.
You can achieve like this.
To convert abcd to 1010101111001101,
class Demo {
public static void main(String args[]) {
String str = "abcd";
for(int i = 0; i < str.length(); i++) {
int number = Integer.parseInt(String.valueOf(str.charAt(i)), 16);
String binary = Integer.toBinaryString(number);
System.out.print(binary);
}
}
}
To convert the 1010101111001101 to abcd
String str = "1010101111001101";
String binary = Long.toHexString(Long.parseLong(str,2));
System.out.print(binary);

How can I split two digit into two different strings?

I have month in, which contains a value such as 12. I am trying to split it into two different strings e.g. a=1 and b=2. How do I do this?
There are several ways to do this.
// Working with Strings ------
String str = "12";
// Get char array
char[] chars = str.toCharArray();
// Two substrings
String firstStr = str.substring(0,1);
String secondStr = str.substring(1,2);
// Working with ints ---------
int i = 12;
int firstInt = i / 10; // Divide
int secondInt = i % 10; // Modulo
Use String.charAt(index) method to return a character and use Character.toString(char) to convert it to String.
Simplest way might be to convert it to a String and then use charAt() to read the characters one by one.
Sounds like a homework question :)
String x = "12";
String[] x_arr= x.split("");
your chars will be located in
x[1]
x[2]
and eventually you can go on with the index if you passed a longer string (like a year).
Just avoid x[0] because it is an empty string.
String splits[] = "12".split("#?") would work.
Use :
str.split("\\w.+")
For Example :
String[] parts = "12".split("\\w.+");
String a = parts[0]
Strign b = parts[1]
You can Take a look here
http://www.roseindia.net/regularexpressions/splitting-string.shtml
Try this:
String input = "12";
System.out.println(input.charAt(0)); // gives '1'
System.out.println(input.charAt(1)); // gives '2'
Furthermore, if you wish to have '1' and '2' as Strings (not as chars), you can do this :
String firstDigit = input.charAt(0) + "";
String secondDigit = input.charAt(1) + "";
Good luck !
Konstantin
EDIT: Lets assume that 'month' is variable of type java.util.Date. Then:
String monthToString = new SimpleDateFormat("MM").format(month);
String firstDigit = monthToString.charAt(0) + "";
String secondDigit = monthToString.charAt(1) + "";
You can use the method substring of class String.
There is the documentation: http://download.oracle.com/javase/1,5.0/docs/api/java/lang/String.html#substring(int, int)
The algorithm is not complex ;)

How do I concatenate two strings in Java?

I am trying to concatenate strings in Java. Why isn't this working?
public class StackOverflowTest {
public static void main(String args[]) {
int theNumber = 42;
System.out.println("Your number is " . theNumber . "!");
}
}
You can concatenate Strings using the + operator:
System.out.println("Your number is " + theNumber + "!");
theNumber is implicitly converted to the String "42".
The concatenation operator in java is +, not .
Read this (including all subsections) before you start. Try to stop thinking the php way ;)
To broaden your view on using strings in Java - the + operator for strings is actually transformed (by the compiler) into something similar to:
new StringBuilder().append("firstString").append("secondString").toString()
There are two basic answers to this question:
[simple] Use the + operator (string concatenation). "your number is" + theNumber + "!" (as noted elsewhere)
[less simple]: Use StringBuilder (or StringBuffer).
StringBuilder value;
value.append("your number is");
value.append(theNumber);
value.append("!");
value.toString();
I recommend against stacking operations like this:
new StringBuilder().append("I").append("like to write").append("confusing code");
Edit: starting in java 5 the string concatenation operator is translated into StringBuilder calls by the compiler. Because of this, both methods above are equal.
Note: Spaceisavaluablecommodity,asthissentancedemonstrates.
Caveat: Example 1 below generates multiple StringBuilder instances and is less efficient than example 2 below
Example 1
String Blam = one + two;
Blam += three + four;
Blam += five + six;
Example 2
String Blam = one + two + three + four + five + six;
Out of the box you have 3 ways to inject the value of a variable into a String as you try to achieve:
1. The simplest way
You can simply use the operator + between a String and any object or primitive type, it will automatically concatenate the String and
In case of an object, the value of String.valueOf(obj) corresponding to the String "null" if obj is null otherwise the value of obj.toString().
In case of a primitive type, the equivalent of String.valueOf(<primitive-type>).
Example with a non null object:
Integer theNumber = 42;
System.out.println("Your number is " + theNumber + "!");
Output:
Your number is 42!
Example with a null object:
Integer theNumber = null;
System.out.println("Your number is " + theNumber + "!");
Output:
Your number is null!
Example with a primitive type:
int theNumber = 42;
System.out.println("Your number is " + theNumber + "!");
Output:
Your number is 42!
2. The explicit way and potentially the most efficient one
You can use StringBuilder (or StringBuffer the thread-safe outdated counterpart) to build your String using the append methods.
Example:
int theNumber = 42;
StringBuilder buffer = new StringBuilder()
.append("Your number is ").append(theNumber).append('!');
System.out.println(buffer.toString()); // or simply System.out.println(buffer)
Output:
Your number is 42!
Behind the scene, this is actually how recent java compilers convert all the String concatenations done with the operator +, the only difference with the previous way is that you have the full control.
Indeed, the compilers will use the default constructor so the default capacity (16) as they have no idea what would be the final length of the String to build, which means that if the final length is greater than 16, the capacity will be necessarily extended which has price in term of performances.
So if you know in advance that the size of your final String will be greater than 16, it will be much more efficient to use this approach to provide a better initial capacity. For instance, in our example we create a String whose length is greater than 16, so for better performances it should be rewritten as next:
Example optimized :
int theNumber = 42;
StringBuilder buffer = new StringBuilder(18)
.append("Your number is ").append(theNumber).append('!');
System.out.println(buffer)
Output:
Your number is 42!
3. The most readable way
You can use the methods String.format(locale, format, args) or String.format(format, args) that both rely on a Formatter to build your String. This allows you to specify the format of your final String by using place holders that will be replaced by the value of the arguments.
Example:
int theNumber = 42;
System.out.println(String.format("Your number is %d!", theNumber));
// Or if we need to print only we can use printf
System.out.printf("Your number is still %d with printf!%n", theNumber);
Output:
Your number is 42!
Your number is still 42 with printf!
The most interesting aspect with this approach is the fact that we have a clear idea of what will be the final String because it is much more easy to read so it is much more easy to maintain.
The java 8 way:
StringJoiner sj1 = new StringJoiner(", ");
String joined = sj1.add("one").add("two").toString();
// one, two
System.out.println(joined);
StringJoiner sj2 = new StringJoiner(", ","{", "}");
String joined2 = sj2.add("Jake").add("John").add("Carl").toString();
// {Jake, John, Carl}
System.out.println(joined2);
You must be a PHP programmer.
Use a + sign.
System.out.println("Your number is " + theNumber + "!");
"+" instead of "."
Use + for string concatenation.
"Your number is " + theNumber + "!"
This should work
public class StackOverflowTest
{
public static void main(String args[])
{
int theNumber = 42;
System.out.println("Your number is " + theNumber + "!");
}
}
For exact concatenation operation of two string please use:
file_names = file_names.concat(file_names1);
In your case use + instead of .
For better performance use str1.concat(str2) where str1 and str2 are string variables.
String.join( delimiter , stringA , stringB , … )
As of Java 8 and later, we can use String.join.
Caveat: You must pass all String or CharSequence objects. So your int variable 42 does not work directly. One alternative is using an object rather than primitive, and then calling toString.
Integer theNumber = 42;
String output =
String // `String` class in Java 8 and later gained the new `join` method.
.join( // Static method on the `String` class.
"" , // Delimiter.
"Your number is " , theNumber.toString() , "!" ) ; // A series of `String` or `CharSequence` objects that you want to join.
) // Returns a `String` object of all the objects joined together separated by the delimiter.
;
Dump to console.
System.out.println( output ) ;
See this code run live at IdeOne.com.
In java concatenate symbol is "+".
If you are trying to concatenate two or three strings while using jdbc then use this:
String u = t1.getString();
String v = t2.getString();
String w = t3.getString();
String X = u + "" + v + "" + w;
st.setString(1, X);
Here "" is used for space only.
In Java, the concatenation symbol is "+", not ".".
"+" not "."
But be careful with String concatenation. Here's a link introducing some thoughts from IBM DeveloperWorks.
You can concatenate Strings using the + operator:
String a="hello ";
String b="world.";
System.out.println(a+b);
Output:
hello world.
That's it
So from the able answer's you might have got the answer for why your snippet is not working. Now I'll add my suggestions on how to do it effectively. This article is a good place where the author speaks about different way to concatenate the string and also given the time comparison results between various results.
Different ways by which Strings could be concatenated in Java
By using + operator (20 + "")
By using concat method in String class
Using StringBuffer
By using StringBuilder
Method 1:
This is a non-recommended way of doing. Why? When you use it with integers and characters you should be explicitly very conscious of transforming the integer to toString() before appending the string or else it would treat the characters to ASCI int's and would perform addition on the top.
String temp = "" + 200 + 'B';
//This is translated internally into,
new StringBuilder().append( "" ).append( 200 ).append('B').toString();
Method 2:
This is the inner concat method's implementation
public String concat(String str) {
int olen = str.length();
if (olen == 0) {
return this;
}
if (coder() == str.coder()) {
byte[] val = this.value;
byte[] oval = str.value;
int len = val.length + oval.length;
byte[] buf = Arrays.copyOf(val, len);
System.arraycopy(oval, 0, buf, val.length, oval.length);
return new String(buf, coder);
}
int len = length();
byte[] buf = StringUTF16.newBytesFor(len + olen);
getBytes(buf, 0, UTF16);
str.getBytes(buf, len, UTF16);
return new String(buf, UTF16);
}
This creates a new buffer each time and copies the old content to the newly allocated buffer. So, this is would be too slow when you do it on more Strings.
Method 3:
This is thread safe and comparatively fast compared to (1) and (2). This uses StringBuilder internally and when it allocates new memory for the buffer (say it's current size is 10) it would increment it's 2*size + 2 (which is 22). So when the array becomes bigger and bigger this would really perform better as it need not allocate buffer size each and every time for every append call.
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
int newCapacity = (oldCapacity << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
private int hugeCapacity(int minCapacity) {
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
if (UNSAFE_BOUND - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > SAFE_BOUND)
? minCapacity : SAFE_BOUND;
}
Method 4
StringBuilder would be the fastest one for String concatenation since it's not thread safe. Unless you are very sure that your class which uses this is single ton I would highly recommend not to use this one.
In short, use StringBuffer until you are not sure that your code could be used by multiple threads. If you are damn sure, that your class is singleton then go ahead with StringBuilder for concatenation.
First method: You could use "+" sign for concatenating strings, but this always happens in print.
Another way: The String class includes a method for concatenating two strings: string1.concat(string2);
import com.google.common.base.Joiner;
String delimiter = "";
Joiner.on(delimiter).join(Lists.newArrayList("Your number is ", 47, "!"));
This may be overkill to answer the op's question, but it is good to know about for more complex join operations. This stackoverflow question ranks highly in general google searches in this area, so good to know.
you can use stringbuffer, stringbuilder, and as everyone before me mentioned, "+". I'm not sure how fast "+" is (I think it is the fastest for shorter strings), but for longer I think builder and buffer are about equal (builder is slightly faster because it's not synchronized).
here is an example to read and concatenate 2 string without using 3rd variable:
public class Demo {
public static void main(String args[]) throws Exception {
InputStreamReader r=new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(r);
System.out.println("enter your first string");
String str1 = br.readLine();
System.out.println("enter your second string");
String str2 = br.readLine();
System.out.println("concatenated string is:" + str1 + str2);
}
}
There are multiple ways to do so, but Oracle and IBM say that using +, is a bad practice, because essentially every time you concatenate String, you end up creating additional objects in memory. It will utilize extra space in JVM, and your program may be out of space, or slow down.
Using StringBuilder or StringBuffer is best way to go with it. Please look at Nicolas Fillato's comment above for example related to StringBuffer.
String first = "I eat"; String second = "all the rats.";
System.out.println(first+second);
Using "+" symbol u can concatenate strings.
String a="I";
String b="Love.";
String c="Java.";
System.out.println(a+b+c);

Categories

Resources