I have an string str of unknown length (but not null) and a given maximum length len, this has to fit in. All I want to do, is to cut the string at len.
I know that I can use
str.substring(0, Math.min(len, str.length()));
but this does not come handy, if I try to write stacked code like this
code = str.replace(" ", "").left(len)
I know that I can write my own function but I would prefer an existing solution. Is there an existing left()-function in Java?
There's nothing built in, but Apache commons has the StringUtils class which has a suitable left function for you.
If you don't want to add the StringUtils Library you can still use it the way you want like so:
String string = (string.lastIndexOf(",") > -1 )?string.substring(0, string.lastIndexOf(",")): string;
Use Split.
String str = "Result string Delimiter Right String";
System.out.println(str.split("Delimiter")[0].trim());
Output: "Result string"
No there is not left() in the String class, as you can refer API. But as #Mark said Apache StringUtils has several methods: leftPad(), rightPad(), center() and repeat(). You can also check
this:http://www.jdocs.com/lang/2.1/org/apache/commons/lang/StringUtils.html
You can use String Format
In this example the format specifier "%-9s" means minimum 9 characters left justified (-).
"%-9.9s" means maximum 9 characters.
System.out.println (String.format("%-9.9s","1234"));
System.out.println (String.format("%-9.9s","123456789ABCD"));
int len=9;
System.out.println (String.format("%-"+len+"."+len+"s","123456789ABCD"));
Prints:
1234
123456789
123456789
in OP's case it would be something like this:
static final int MAXLEN=9;
code = String.format("%-"+MAXLEN+"."+MAXLEN+"s",str.replace(" ", ""));
put the below function in a class:
public static String getLeftString(String st,int length){
int stringlength=st.length();
if(stringlength<=length){
return st;
}
return st.substring((stringlength-length));
}
in my case I want to get date only.
String s = "date:2021-01-01";
int n = s.length() - 10; //10 was the length of the date
String result = s.substring(n);
the result will be "2021-01-01";
Related
Context:
I wish to have a fixed string lenght since I'm formatting an output file, I built 2 functions that should be applied to string based on my string length.
First function: if you want a string X char long, but you got one which is X-Y, this adds spaces 'till desired length is reached, in this particular case, Y. This seems correct, it works
public String formatSpace(String s, int desiredlength){
while (s.length()<desiredlength){
s+=" ";
}
return s;
}
Second function: if you want a string X char long but you got one which is X+Y, this "removes" char until desired length is reached, in this particular case, Y. This seems to be wrong.
public String truncString(String s, int desiredlength){
return s.substr(0,s.length()-desiredlenght);
}
Error:
I apply these two based on string length that I test in another part of code:
[...]//here i built my class
int maxlen = 60;
[...] //here there is more code but it just collects data and I already tested fields
if (field.length()<maxlen){
field = formatSpace(field,maxlen);
}else if (field.length()>maxlen){
field = truncString(field,maxlen);
}
[...] //here i put string on file
Error I get is about string index being negative, I don't know why, I tried code on paper (yes, I know it's dumb) but it works there
Why second function is not working?
Also, it would be better to make one function which format my string, how should I make it?
Solution:
Thanks to everyone who commented, I solved my problem with this single function I wrote, I don't even test string anymore, if they fit my length they're ok, else I format them:
private String formatString(String s, int length) {
while (s.length() < length) {
s += " ";
}
return s.substring(0, length);
}
Second argument in substring function is the length of your new String. Why do you have a substraction ?
This should work :
public String truncString(String s, int desiredlength){
return s.substr(0,desiredlenght);
}
I usually use something like:
private static String spaces(int width) {
// May be more efficient ways of doing this.
return String.join("", Collections.nCopies(width, " "));
}
private static String fixedWidth(String s, int width, boolean padLeft) {
String spaces = spaces(Math.max(0,width-s.length()));
return (padLeft ? spaces + s : s + spaces).substring(0, width);
}
public void test(String[] args) {
String[] tests = {"Hello", "Loooooooooooooong!!!"};
for ( String t: tests) {
System.out.println(fixedWidth(t,10,false));
System.out.println(fixedWidth(t,10,true));
}
}
Or you can try this approach for a simple one line solution.
String test="type something here";
int desiredLength=15;
System.out.println(String.format("%1$-"+desiredLength+"s", test.substring(0, desiredLength)));
The idea is => substring first to the desired length (this will happen if string is longer) and then use String format to fill to desired length with spaces ( %1$-10s is the format for left aligned string filled to 10 spaces).
You have a typo. Inside truncString you write desiredlenght instead of desiredlength.
The problem in the second function is a logic problem. Imagine you're desired length is 4 and you introduce a String which length is 6. If you do the String length - desired length you're going to obtain a String which length is 2.
A way to fix this problem is to return directly the substr: return s.substr(0,desiredLenght)
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);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to upper case every first letter of word in a string?
Most efficient way to make the first character of a String lower case?
I want to convert the first letter of a string to upper case. I am attempting to use replaceFirst() as described in JavaDocs, but I have no idea what is meant by regular expression.
Here is the code I have tried so far:
public static String cap1stChar(String userIdea)
{
String betterIdea, userIdeaUC;
char char1;
userIdeaUC = userIdea.toUpperCase();
char1 = userIdeaUC.charAt(0);
betterIdea = userIdea.replaceFirst(char1);
return betterIdea;
}//end cap1stChar
The compiler error is that the argument lists differ in lengths. I presume that is because the regex is missing, however I don't know what that is exactly.
Regular Expressions (abbreviated "regex" or "reg-ex") is a string that defines a search pattern.
What replaceFirst() does is it uses the regular expression provided in the parameters and replaces the first result from the search with whatever you pass in as the other parameter.
What you want to do is convert the string to an array using the String class' charAt() method, and then use Character.toUpperCase() to change the character to upper case (obviously). Your code would look like this:
char first = Character.toUpperCase(userIdea.charAt(0));
betterIdea = first + userIdea.substring(1);
Or, if you feel comfortable with more complex, one-lined java code:
betterIdea = Character.toUpperCase(userIdea.charAt(0)) + userIdea.substring(1);
Both of these do the same thing, which is converting the first character of userIdea to an upper case character.
Or you can do
s = Character.toUpperCase(s.charAt(0)) + s.substring(1);
public static String cap1stChar(String userIdea)
{
char[] stringArray = userIdea.toCharArray();
stringArray[0] = Character.toUpperCase(stringArray[0]);
return userIdea = new String(stringArray);
}
Comilation error is due arguments are not properly provided, replaceFirst accepts regx as initial arg. [a-z]{1} will match string of simple alpha characters of length 1.
Try this.
betterIdea = userIdea.replaceFirst("[a-z]{1}", userIdea.substring(0,1).toUpperCase())
String toCamelCase(String string) {
StringBuffer sb = new StringBuffer(string);
sb.replace(0, 1, string.substring(0, 1).toUpperCase());
return sb.toString();
}
userIdeaUC = userIdea.substring(0, 1).toUpperCase() + userIdea.length() > 1 ? userIdea.substring(1) : "";
or
userIdeaUC = userIdea.substring(0, 1).toUpperCase();
if(userIdea.length() > 1)
userIdeaUC += userIdea.substring(1);
For completeness, if you wanted to use replaceFirst, try this:
public static String cap1stChar(String userIdea)
{
String betterIdea = userIdea;
if (userIdea.length() > 0)
{
String first = userIdea.substring(0,1);
betterIdea = userIdea.replaceFirst(first, first.toUpperCase());
}
return betterIdea;
}//end cap1stChar
I am trying to concatenate and trying to parse at the same time. I am right now making a excel like program where I can say a1 = "Hello" + "World" and in the cell of A1 have it say HelloWorld. I just need to know how to parse the adding sign and connect those two words. Please tell me if you need more code to understand this, like the runner.
This is my parseInput class :
public class ParseInput {
private static String inputs;
static int col;
private static int row;
private static String operation;
private static Value field;
public static void parseInput(String input){
//splits the input at each regular expression match. \w is used for letters and \d && \D for integers
inputs = input;
Scanner tokens = new Scanner(inputs);
String none0 = tokens.next();
#SuppressWarnings("unused")
String none1 = tokens.next();
operation = tokens.nextLine().substring(1);
String[] holder = new String[2];
String regex = "(?<=[\\w&&\\D])(?=\\d)";
holder = none0.split(regex);
row = Integer.parseInt(holder[1]);
col = 0;
int counter = -1;
char temp = holder[0].charAt(0);
char check = 'a';
while(check <= temp){
if(check == temp){
col = counter +1;
}
counter++;
check = (char) (check + 1);
}
System.out.println(col);
System.out.println(row);
System.out.println(operation);
setField(Value.parseValue(operation));
Spreadsheet.changeCell(row, col, field);
}
public static Value getField() {
return field;
}
public static void setField(Value field) {
ParseInput.field = field;
}
}
This is actually a pretty complicated problem unless you can constrain input to a very small subset of what Excel accepts. If not then you'll probably want to look into something like ANTLR. However, assuming the above input then you'll want to do something like:
Split the string on the equal sign into s1 and s2
Split s2 on the plus sign into s3 and s4.
Trim all the strings, remove the quotes around s3 and s4.
Concatenate s3 and s4 and assign to your datastore indexed by s1.
Depending on how complex your concatenation needs are you can either use string concatenation or a StringBuilder:
result = "" + s3 + s4; // string concatenation
result = new StringBuilder().append(s3).append(s4).toString(); // StringBuilder
Let me know if you have any questions about any of the steps detailed above.
Details on (1) above, assuming input is a1 = "Hello" + "World":
String[] strings = input.split("=");
String s1 = strings[0].trim(); // a1
String s2 = strings[1].trim(); // "Hello" + "World"
strings = s2.split("+");
String s3 = strings[0].trim().replaceAll("^\"", "").replaceAll("\"$", "") // Hello
String s4 = strings[1].trim().replaceAll("^\"", "").replaceAll("\"$", ""); // World
String field = s3 + s4;
String colString = s1.replaceAll("[\\d]", ""); // a
String rowString = s1.replaceAll("[\\D]", ""); // 1
int col = colString.charAt(0) - 'a'; // 0
int row = Integer.parseInt(rowString);
Spreadsheet.changeCell(row, col, field);
I suggest you to implement your custom grammar using a parser generator like JavaCC.
Here you can find a simple tutorial.
I believe this is the better solution because in this way you can handle every expression you need.
Are you sure you want to use all the classes you are using? To parse something like "a=b+c+d.." (assuming you are not trying to validate), easiest and possibly the most efficient way is to use split API in Java lang String
Then join whatever is required using StringBuilder
You need to design and implement a parser and an evaluator. And before that, you need to design the language that your parser/evaluator is going to evaluate.
How to do it.
If your language is really simple, you can get away with parsing it by hand, using something like StringTokenizer to do the tokenization,
Otherwise, you are probably best off learning to use a Java "parser generator" such as JavaCC or ANTLR.
Either way, you need to do some background reading to understand all of the terminology. You could start with Wikipedia and/or the tutorial material from one of the parser generators. Alternatively, there are good textbooks on this topic.
In addition to what Abdullah said, if you really want to save every single ounce of memory you can, you should use the StringBuilder instead of the String concatenation. I believe i read somewhere before that the String concatenation make a new string object for each concatenations while the StringBuilder will add them all to a single String. Shouldn't matter too much though.
In my early life I made an equation evaluator in your style. It cost me huge code and complexity, because of my unawareness about Expression trees. But now with this you will be able to add more capabilities to your parser easily and with native JAVA codes. You will get tons of example of using Expression Trees.
I need to trim a String in java so that:
The quick brown fox jumps over the laz dog.
becomes
The quick brown...
In the example above, I'm trimming to 12 characters. If I just use substring I would get:
The quick br...
I already have a method for doing this using substring, but I wanted to know what is the fastest (most efficient) way to do this because a page may have many trim operations.
The only way I can think off is to split the string on spaces and put it back together until its length passes the given length. Is there an other way? Perhaps a more efficient way in which I can use the same method to do a "soft" trim where I preserve the last word (as shown in the example above) and a hard trim which is pretty much a substring.
Thanks,
Below is a method I use to trim long strings in my webapps.
The "soft" boolean as you put it, if set to true will preserve the last word.
This is the most concise way of doing it that I could come up with that uses a StringBuffer which is a lot more efficient than recreating a string which is immutable.
public static String trimString(String string, int length, boolean soft) {
if(string == null || string.trim().isEmpty()){
return string;
}
StringBuffer sb = new StringBuffer(string);
int actualLength = length - 3;
if(sb.length() > actualLength){
// -3 because we add 3 dots at the end. Returned string length has to be length including the dots.
if(!soft)
return escapeHtml(sb.insert(actualLength, "...").substring(0, actualLength+3));
else {
int endIndex = sb.indexOf(" ",actualLength);
return escapeHtml(sb.insert(endIndex,"...").substring(0, endIndex+3));
}
}
return string;
}
Update
I've changed the code so that the ... is appended in the StringBuffer, this is to prevent needless creations of String implicitly which is slow and wasteful.
Note: escapeHtml is a static import from apache commons:
import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
You can remove it and the code should work the same.
Here is a simple, regex-based, 1-line solution:
str.replaceAll("(?<=.{12})\\b.*", "..."); // How easy was that!? :)
Explanation:
(?<=.{12}) is a negative look behind, which asserts that there are at least 12 characters to the left of the match, but it is a non-capturing (ie zero-width) match
\b.* matches the first word boundary (after at least 12 characters - above) to the end
This is replaced with "..."
Here's a test:
public static void main(String[] args) {
String input = "The quick brown fox jumps over the lazy dog.";
String trimmed = input.replaceAll("(?<=.{12})\\b.*", "...");
System.out.println(trimmed);
}
Output:
The quick brown...
If performance is an issue, pre-compile the regex for an approximately 5x speed up (YMMV) by compiling it once:
static Pattern pattern = Pattern.compile("(?<=.{12})\\b.*");
and reusing it:
String trimmed = pattern.matcher(input).replaceAll("...");
Please try following code:
private String trim(String src, int size) {
if (src.length() <= size) return src;
int pos = src.lastIndexOf(" ", size - 3);
if (pos < 0) return src.substring(0, size);
return src.substring(0, pos) + "...";
}
Try searching for the last occurence of a space that is in a position less or more than 11 and trim the string there, by adding "...".
Your requirements aren't clear. If you have trouble articulating them in a natural language, it's no surprise that they'll be difficult to translate into a computer language like Java.
"preserve the last word" implies that the algorithm will know what a "word" is, so you'll have to tell it that first. The split is a way to do it. A scanner/parser with a grammar is another.
I'd worry about making it work before I concerned myself with efficiency. Make it work, measure it, then see what you can do about performance. Everything else is speculation without data.
How about:
mystring = mystring.replaceAll("^(.{12}.*?)\b.*$", "$1...");
I use this hack : suppose that the trimmed string must have 120 of length :
String textToDisplay = textToTrim.substring(0,(textToTrim.length() > 120) ? 120 : textToTrim.length());
if (textToDisplay.lastIndexOf(' ') != textToDisplay.length() &&textToDisplay.length()!=textToTrim().length()) {
textToDisplay = textToDisplay + textToTrim.substring(textToDisplay.length(),textToTrim.indexOf(" ", textToDisplay.length()-1))+ " ...";
}