ive got a problem with string conversion.
I am trying to implement a system where numbers (BigDecimal) are printed to the screen when they are updated.
Therefore i created a subclass of BigDecimal (dpzahl) to detect the updated number and send a updaterequest to the ui.
So basically: i save the string (text) from String.xml. example:
"value of %s: %s"
and i save the references of the arguments in argument.
these references can be Strings, SpannableStrings or dpzahl's.
But while preparing the string.format ive got a problem:
Log.d(MainActivity.LOGTAG,"update request is executed");
final Object[] ARGS = new CharSequence[argumente.size()]; //to be put into the formater
int i = 0;
for(Object ooo: arguments) { // private ArrayList<Object> arguments; is a class variable
if (ooo instanceof dpzahl) { // dpzahl extends BigDecimal to get the number i want to format
ARGS[i] = haupt.format_bigies(((dpzahl) ooo).get()); //get the formated string
Log.d(MainActivity.LOGTAG,"number print:"+ARGS[i].toString());
}if(ooo instanceof SpannableString){ //some other arguments i may need in the string.format argument list
ARGS[i] = ((SpannableString)ooo);
}else{ //for any other object, mostly Strings
ARGS[i] = ooo.toString();
}
if (ooo instanceof dpzahl) { //only for debugprint
Log.d(MainActivity.LOGTAG,"loopvalue dpzahl:"+ARGS[i].toString());
}
Log.d(MainActivity.LOGTAG,"loopvalue:"+ARGS[i].toString());
i++;
}
for(Object ooo: ARGS) { //only for debugprint
if(ooo instanceof String){
Log.d(MainActivity.LOGTAG, "againarg Stirng:" + ((String)ooo));
}else if(ooo instanceof SpannableString) {
Log.d(MainActivity.LOGTAG, "againarg SpannableString:" + ((SpannableString)ooo).toString());
}
Log.d(MainActivity.LOGTAG, "againarg Object:" + ooo.toString());
}
sicht.post(new Runnable() {
#Override
public void run() {
Log.d(MainActivity.LOGTAG,"allargs:"+ Arrays.toString(ARGS));
view.setText(SpanFormatter.format(text, ARGS));//Copyright © 2014 George T. Steel, replace string.format for SpannableString
view.invalidate();//the linked TextView
}
});
If i put in the SpannableString "testvalue" and the BigDecimal expression for 4 the output is
output:
update request is executed
loopvalue:testvalue
formated BigDecimal:4
number print:4
loopvalue dpzahl:4.000000000
loopvalue:4.000000000
againarg SpannableString:testvalue
againarg Object:testvalue
againarg Stirng:4.000000000
againarg Object:4.000000000
allargs:[testvalue , 4.000000000]
so the TextView String should be "value of testvalue: 4" but it is "value of testvalue: 4.000000000"
So why have the Value of ARGS[1] first the value of String "4" and later the value "4.000000000" before it is passed to the formater?
ps: the problem appears when i implemented the SpannableString to the formater, before this, the line
final Object[] ARGS = new CharSequence[argumente.size()];
was
final Object[] ARGS = new String[argumente.size()];
and all work fine. But SpannableString does not extend Strings so i need the next upper lowest common denominator which is CharSequence.
pp: using
final Object[] ARGS = new Object[argumente.size()];
does not help.
Change
if(ooo instanceof SpannableString)
to
else if(ooo instanceof SpannableString)
Related
I tried to move codebase to Kotlin from Java. But I found strange behavior in String.format.
I have both same codes (and feature, also) in Kotlin and Java.
fun callScriptMethod(methodName: String, vararg args: Any): String {
var format = methodName
if (!format.contains("javascript:")) {
format = String.format("javascript:%s", format)
}
val objects = mutableListOf<Any>()
for (arg in args) objects.add(arg)
if (!objects.isEmpty()) {
format += "("
var i = 0
val icnt = objects.size
while (i < icnt) {
format += "\'%s\'"
if (i != icnt - 1) {
format += ", "
}
i++
}
format += ")"
} else {
format += "()"
}
val message = String.format(Locale.getDefault(), format, args)
return message
}
public static String callScriptMethod(String methodName, Object... args) {
String format = methodName;
if (!format.contains("javascript:")) {
format = String.format("javascript:%s", format);
}
List<Object> objects = Arrays.asList(args);
if (!objects.isEmpty()) {
format += "(";
for (int i = 0, icnt = objects.size(); i < icnt; i++) {
format += "\'%s\'";
if (i != icnt - 1) {
format += ", ";
}
}
format += ")";
} else {
format += "()";
}
String message = String.format(format, args);
return message;
}
and some test code.
fun main() {
val result = Java.callScriptMethod("nativeCallback", "1", "d8d8441n24n134n",
"dasqhjidhkdhaskjdfhawoiudnqwaidnqwioldjnqawskld:djoashdojashdlkjasdjhas", "0")
println(result)
val result2 = Kotlin.callScriptMethod("nativeCallback", "1", "d8d8441n24n134n",
"dasqhjidhkdhaskjdfhawoiudnqwaidnqwioldjnqawskld:djoashdojashdlkjasdjhas", "0")
println(result2)
}
I can expect result is javascript:nativeCallback('1', 'd8d8441n24n134n', 'dasqhjidhkdhaskjdfhawoiudnqwaidnqwioldjnqawskld:djoashdojashdlkjasdjhas', '0').
But the version of Kotlin has exception MissingFormatArgumentException.
So, I tried to debug these codes to know the format is generated successfully.
Java: javascript:nativeCallback('%s', '%s', '%s', '%s')
Kotlin: javascript:nativeCallback('%s', '%s', '%s', '%s')
Both are the same result and have same args but has a different result.
javascript:nativeCallback('1', 'd8d8441n24n134n', 'dasqhjidhkdhaskjdfhawoiudnqwaidnqwioldjnqawskld:djoashdojashdlkjasdjhas', '0')
Exception in thread "main" java.util.MissingFormatArgumentException: Format specifier '%s'
at java.util.Formatter.format(Formatter.java:2519)
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2981)
at Kotlin.callScriptMethod(Kotlin.kt:31)
at TestKt.main(test.kt:11)
at TestKt.main(test.kt)
So, I want to know what is the problem. How can i do?
As vararg becomes an array once entering the function body, you have to use the spread operator in order to pass it as vararg. https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs
When we call a vararg-function, we can pass arguments one-by-one, e.g. asList(1, 2, 3), or, if we already have an array and want to pass its contents to the function, we use the spread operator (prefix the array with *):
val message = String.format( format, *args)
The difference with Java is that Java actually allows passing an array as vararg directly, see this SO post: Can I pass an array as arguments to a method with variable arguments in Java?
i.e. Object... in Java is technically identical to Object[], there are no "real" vararg things in Java, while vararg is a real different thing in Kotlin.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I need to parse the command line arguments and transform them into a Java object.
My command line to run the Java .jar:
java -cp "combo.jar" com.ascurra.Main --time=3 --limit=5000 --initDate=2017-01-01.13:00:00
I need transform the arguments --time=3 --limit=5000 --initDate=2017-01-01.13:00:00 into an object and save it to my database.
How do this in an elegant way?
First of all, create a Class with the corresponding fields
class Entry {
private int time;
private int limit;
private Date initDate;
public Entry() {
}
public Date getInitDate() {
return initDate;
}
public void setInitDate(Date initDate) {
this.initDate = initDate;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}
Then create an object of this class and parse the arguments to set the values
public static void main(String[] args) {
ArrayList<String> options = new ArrayList<>();
for (String arg : args) { // get the options from the arguments
if (arg.startsWith("--")) {
options.add(arg.replace("--", ""));
}
}
Entry entry = new Entry();
for (String option : options) {
String[] pair = option.split("=");
if (pair.length == 2) {
if (pair[0].equals("time")) { // parse time option
entry.setTime(Integer.parseInt(pair[1]));
} else if (pair[0].equals("limit")) { // parse limit option
entry.setLimit(Integer.parseInt(pair[1]));
} else if (pair[0].equals("initDate")) { // parse initDate option
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd.HH:mm:ss");
try {
entry.setInitDate(sdf.parse(pair[1]));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
}
System.out.println(entry.getLimit() + " , " + entry.getTime() + " , "
+ entry.getInitDate());
}
I'd create a stream of the args array, map to retain the part of the string needed i.e:
String[] resultArray = Arrays.stream(args)
.map(s -> s.substring(s.indexOf("=") + 1))
.toArray(String[]::new);
the array should now contain:
[3, 5000, 2017-01-01.13:00:00]
in which case you can index into this array, then convert to any other type needed and populate your custom object.
Alternatively, as there are only 3 arguments, you could skip creating the stream entirely and just index into the array along with the use of substring to retain the parts needed. However, the approach above is more adaptable as if you were to enter more arguments, you need not change anything within your code in terms of retrieving the arguments.
how do this in an elegant way?
These three information(--time=3 --limit=5000 --initDate=2017-01-01.13:00:00) are passed as a specific element in String[] args of the main class.
Parsing them is really not a complex task (String.substring() or a regex will do the job).
But a good parser should also be able to not be annoyed by the order of arguments and should also think to produce relevant debugging information during data mapping to specific type as date or numeric types.
At last, adding or removing a supported parameter should be easy and safe and getting commands help could also be desirable.
So as first advise, if you can use a library, don't reinvent the wheel and use
Apache Commons CLI or better use arg4j that is reall simple to use and avoid boiler plate code.
If you cannot, at least inspire you from them.
Apache Commons CLI example
For example to create Options (arguments) :
public static final String TIME_ARG = "time";
public static final String LIMIT_ARG = "limit";
...
Options options = new Options();
options.addOption("t", TIME_ARG, true, "current time");
options.addOption("l", LIMIT_ARG, true, "limit of ...");
...
Then parse Options and retrieve value of it:
public static void main(String[] args) {
...
try{
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);
...
// then retrieve arguments
Integer time = null;
Integer limit = null;
LocalDateTime localDateTime = null;
String timeRaw = cmd.getOptionValue(TIME_ARG);
if (timeRaw.matches("\\d*")) {
time = Integer.valueOf(timeRaw);
}
...and so for until you create your object to save
MyObj obj = new MyObj(time, limit, localDateTime);
...
}
catch(ParseException exp ) {
System.out.println( "Unexpected exception:" + exp.getMessage() );
}
}
args4j example
args4j is much straight to use.
Besides, it provides some converters (from String to specific types) but date conversion is not provided out of the box.
So you should create your own handler to do that.example.
In the example, LocalDateTimeOptionHandler must so implement [OptionHandler][3].
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.OptionHandlerFilter;
public class SampleMain {
#Option(name = "--time", usage = "...")
private Integer time;
#Option(name = "--limit", usage = "..")
private Integer limit;
#Option(name="--initDate", handler=LocalDateTimeOptionHandler.class, usage="...")
private LocalDateTime initDate;
public static void main(String[] args) throws IOException {
new SampleMain().doMain(args);
}
public void doMain(String[] args) throws IOException {
CmdLineParser parser = new CmdLineParser(this);
try {
// parse the arguments.
parser.parseArgument(args);
} catch (CmdLineException e) {
System.err.println(e.getMessage());
System.err.println("java SampleMain [options...] arguments...");
parser.printUsage(System.err);
System.err.println(" Example: java SampleMain" + parser.printExample(OptionHandlerFilter.ALL));
return;
}
if (time != null)
System.out.println("-time is set");
if (limit != null)
System.out.println("-limit is set");
if (initDate != null)
System.out.println("-initDate is set");
}
}
I am working with a code where I want fill several string place holders with another strings. This is the example text I have used to test my code.
String myStr = "Media file %s of size %s has been approved"
This is how I fill the place holders. Since I expect to use several place holders I have used java Map<>.
Map<String, String> propMap = new HashMap<String,String>();
propMap.put("file name","20mb");
String newNotification = createNotification(propMap);
I used following method to create the string.
public String createNotification(Map<String, String> properties){
String message = "";
message = String.format(myStr, properties);
return message;
}
How do I replace two of '%s' with "file name" and "20mb"?
That's not what a Map is intended to do.
What you add is an entry "file name" -> "20 mb", which basically means the property "file name" has the value "20 mb". What you are trying to do with it is "maintain a tuple of items".
Note that the formatting string has a fixed amount of placeholder; you want a data structure that contains exactly the same amount of items; so essentially an array or a List.
Thus, what you want to have is
public String createNotification(String[] properties) {
assert(properties.length == 2); // you might want to really check this, you will run into problems if it's false
return String.format("file %s has size %s", properties);
}
If you want to create notifications of all items in a map, you need to do something like this:
Map<String,String> yourMap = //...
for (Entry<String,String> e : yourMap) {
System.out.println(createNotification(e.getKey(), e.getValue()));
}
Your approach to String#format is wrong.
It expects a variable amount of objects to replace the placeholders as the second argument, not a map. To group them all together, you can use an array or a list.
String format = "Media file %s of size %s has been approved";
Object[] args = {"file name", "20mb"};
String newNotification = String.format(format, args);
You can simply do this formatting using var-args:
String myStr = "Media file %s of size %s has been approved";
String newNotification = createNotification(myStr, "file name", "20mb");
System.out.println(newNotification);
Pass var-args in createNotification method, here is the code:
public static String createNotification(String myStr, String... strings){
String message = "";
message=String.format(myStr, strings[0], strings[1]);
return message;
}
I think %s is Python’s grammar to place holder, can’t use this in Java environment; and your method createNotification() defined needs two parameters, can’t only give one.
After trying several ways finally found a good solution. Place holders must be like this [placeholder] .
public String createNotification(){
Pattern pattern = Pattern.compile("\\[(.+?)\\]");
Matcher matcher = pattern.matcher(textTemplate);
HashMap<String,String> replacementValues = new HashMap<String,String>();
StringBuilder builder = new StringBuilder();
int i = 0;
while (matcher.find()) {
String replacement = replacementValues.get(matcher.group(1));
builder.append(textTemplate.substring(i, matcher.start()));
if (replacement == null){ builder.append(matcher.group(0)); }
else { builder.append(replacement); }
i = matcher.end();
}
builder.append(textTemplate.substring(i, textTemplate.length()));
return builder.toString()
}
What is the best way to treat null values in Java MessageFormat
MessageFormat.format("Value: {0}",null);
=> Value: null
but actually a "Value: " would be nice.
Same with date
MessageFormat.format("Value: {0,date,medium}",null);
=> Value: null
a "Value: " whould be much more appreciated.
Is there any way to do this? I tried choice
{0,choice,null#|notnull#{0,date,dd.MM.yyyy – HH:mm:ss}}
which results in invalid choice format, what is correct to check for "null" or "not null"?
MessageFormat is only null-tolerant; that is, it will handle a null argument. If you want to have a default value appear instead of something if the value you're working with is null, you have two options:
You can either do a ternary...
MessageFormat.format("Value: {0}", null == value ? "" : value));
...or use StringUtils.defaultIfBlank() from commons-lang instead:
MessageFormat.format("Value: {0}", StringUtils.defaultIfBlank(value, ""));
Yes, you cant. Look at javadoc. Unfortunately, it dind't work with NULL.
Try use optional
Optional.ofNullable(value).orElse(0)
Or see example how to use ChoiceFormat and MessageFormat.
For more sophisticated patterns, you can use a ChoiceFormat to produce correct forms for singular and plural:
MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
double[] filelimits = {0,1,2};
String[] filepart = {"no files","one file","{0,number} files"};
ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
form.setFormatByArgumentIndex(0, fileform);
int fileCount = 1273;
String diskName = "MyDisk";
Object[] testArgs = {new Long(fileCount), diskName};
System.out.println(form.format(testArgs));
The output with different values for fileCount:
The disk "MyDisk" contains no files.
The disk "MyDisk" contains one file.
The disk "MyDisk" contains 1,273 files.
You can create the ChoiceFormat programmatically, as in the above example, or by using a pattern. See ChoiceFormat for more information.
form.applyPattern(
"There {0,choice,0#are no files|1#is one file|1
I need that now in my generator class by a mask.
Reason:
User can save mask with multiple types say "{0} {1,number,000} {2,date,MMyyyy}. And user have data where can be nulls. For result i use MessageFormat class. And want empty string without default 'null' text.
Null check is not that easy, because it will means replace pattern that is used for many records (not just one). And default empty value don't exists for number or date.
So if someone still needs solution. I give my.
Add this methods/classes (I have all in one class)
private static Object[] replaceNulls2NullValues( Object[] values ) {
for ( int i = 0; i < values.length; i++ )
if ( values[i] == null )
values[i] = NullFormatValue.NULL_FORMAT_VALUE;
return values;
}
private static MessageFormat modifyFormaterFormats( MessageFormat formater ) {
formater.setFormats( Arrays.stream( formater.getFormats() ).map( ( f ) -> ( f != null ) ? new NullHandlingFormatWrapper( f ) : null ).toArray( ( l ) -> new Format[l] ) );
return formater;
}
private static final class NullFormatValue {
static final Object NULL_FORMAT_VALUE = new NullFormatValue();
private NullFormatValue() {
}
#Override
public String toString() {
return "";
}
}
private static class NullHandlingFormatWrapper extends Format {
protected Format wrappedFormat;
public NullHandlingFormatWrapper( Format format ) {
wrappedFormat = format;
}
#Override
public StringBuffer format( Object obj, StringBuffer toAppendTo, FieldPosition pos ) {
if ( !( obj instanceof NullFormatValue ) )
wrappedFormat.format( obj, toAppendTo, pos );
return toAppendTo;
}
#Override
public Object parseObject( String source, ParsePosition pos ) {
return wrappedFormat.parseObject( source, pos );
}
}
and for result call
modifyFormaterFormats( new MessageFormat( pattern ) ).format( replaceNulls2NullValues( parameters ) );
I am using the String split method and I want to have the last element.
The size of the Array can change.
Example:
String one = "Düsseldorf - Zentrum - Günnewig Uebachs"
String two = "Düsseldorf - Madison"
I want to split the above Strings and get the last item:
lastone = one.split("-")[here the last item] // <- how?
lasttwo = two.split("-")[here the last item] // <- how?
I don't know the sizes of the arrays at runtime :(
You could use lastIndexOf() method on String
String last = string.substring(string.lastIndexOf('-') + 1);
Save the array in a local variable and use the array's length field to find its length. Subtract one to account for it being 0-based:
String[] bits = one.split("-");
String lastOne = bits[bits.length-1];
Caveat emptor: if the original string is composed of only the separator, for example "-" or "---", bits.length will be 0 and this will throw an ArrayIndexOutOfBoundsException. Example: https://onlinegdb.com/r1M-TJkZ8
You can use the StringUtils class in Apache Commons:
StringUtils.substringAfterLast(one, "-");
using a simple, yet generic, helper method like this:
public static <T> T last(T[] array) {
return array[array.length - 1];
}
you can rewrite:
lastone = one.split("-")[..];
as:
lastone = last(one.split("-"));
String str = "www.anywebsite.com/folder/subfolder/directory";
int index = str.lastIndexOf('/');
String lastString = str.substring(index +1);
Now lastString has the value "directory"
Gathered all possible ways together!!
By using lastIndexOf() & substring() methods of Java.lang.String
// int firstIndex = str.indexOf( separator );
int lastIndexOf = str.lastIndexOf( separator );
String begningPortion = str.substring( 0, lastIndexOf );
String endPortion = str.substring( lastIndexOf + 1 );
System.out.println("First Portion : " + begningPortion );
System.out.println("Last Portion : " + endPortion );
split()Java SE 1.4. Splits the provided text into an array.
String[] split = str.split( Pattern.quote( separator ) );
String lastOne = split[split.length-1];
System.out.println("Split Array : "+ lastOne);
How to split String before first comma?
Java 8 sequential ordered stream from an array.
String firstItem = Stream.of( split )
.reduce( (first,last) -> first ).get();
String lastItem = Stream.of( split )
.reduce( (first,last) -> last ).get();
System.out.println("First Item : "+ firstItem);
System.out.println("Last Item : "+ lastItem);
Apache Commons Langjar « org.apache.commons.lang3.StringUtils
String afterLast = StringUtils.substringAfterLast(str, separator);
System.out.println("StringUtils AfterLast : "+ afterLast);
String beforeLast = StringUtils.substringBeforeLast(str, separator);
System.out.println("StringUtils BeforeLast : "+ beforeLast);
String open = "[", close = "]";
String[] groups = StringUtils.substringsBetween("Yash[777]Sam[7]", open, close);
System.out.println("String that is nested in between two Strings "+ groups[0]);
Guava: Google Core Libraries for Java. « com.google.common.base.Splitter
Splitter splitter = Splitter.on( separator ).trimResults();
Iterable<String> iterable = splitter.split( str );
String first_Iterable = Iterables.getFirst(iterable, "");
String last_Iterable = Iterables.getLast( iterable );
System.out.println(" Guava FirstElement : "+ first_Iterable);
System.out.println(" Guava LastElement : "+ last_Iterable);
Scripting for the Java Platform « Run Javascript on the JVM with Rhino/Nashorn
Rhino « Rhino is an open-source implementation of JavaScript written entirely in Java. It is typically embedded into Java applications to provide scripting to end users. It is embedded in J2SE 6 as the default Java scripting engine.
Nashorn is a JavaScript engine developed in the Java programming language by Oracle. It is based on the Da Vinci Machine and has been released with Java 8.
Java Scripting Programmer's Guide
public class SplitOperations {
public static void main(String[] args) {
String str = "my.file.png.jpeg", separator = ".";
javascript_Split(str, separator);
}
public static void javascript_Split( String str, String separator ) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// Script Variables « expose java objects as variable to script.
engine.put("strJS", str);
// JavaScript code from file
File file = new File("E:/StringSplit.js");
// expose File object as variable to script
engine.put("file", file);
try {
engine.eval("print('Script Variables « expose java objects as variable to script.', strJS)");
// javax.script.Invocable is an optional interface.
Invocable inv = (Invocable) engine;
// JavaScript code in a String
String functions = "function functionName( functionParam ) { print('Hello, ' + functionParam); }";
engine.eval(functions);
// invoke the global function named "functionName"
inv.invokeFunction("functionName", "function Param value!!" );
// evaluate a script string. The script accesses "file" variable and calls method on it
engine.eval("print(file.getAbsolutePath())");
// evaluate JavaScript code from given file - specified by first argument
engine.eval( new java.io.FileReader( file ) );
String[] typedArray = (String[]) inv.invokeFunction("splitasJavaArray", str );
System.out.println("File : Function returns an array : "+ typedArray[1] );
ScriptObjectMirror scriptObject = (ScriptObjectMirror) inv.invokeFunction("splitasJavaScriptArray", str, separator );
System.out.println("File : Function return script obj : "+ convert( scriptObject ) );
Object eval = engine.eval("(function() {return ['a', 'b'];})()");
Object result = convert(eval);
System.out.println("Result: {}"+ result);
// JavaScript code in a String. This code defines a script object 'obj' with one method called 'hello'.
String objectFunction = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
engine.eval(objectFunction);
// get script object on which we want to call the method
Object object = engine.get("obj");
inv.invokeMethod(object, "hello", "Yash !!" );
Object fileObjectFunction = engine.get("objfile");
inv.invokeMethod(fileObjectFunction, "hello", "Yashwanth !!" );
} catch (ScriptException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static Object convert(final Object obj) {
System.out.println("\tJAVASCRIPT OBJECT: {}"+ obj.getClass());
if (obj instanceof Bindings) {
try {
final Class<?> cls = Class.forName("jdk.nashorn.api.scripting.ScriptObjectMirror");
System.out.println("\tNashorn detected");
if (cls.isAssignableFrom(obj.getClass())) {
final Method isArray = cls.getMethod("isArray");
final Object result = isArray.invoke(obj);
if (result != null && result.equals(true)) {
final Method values = cls.getMethod("values");
final Object vals = values.invoke(obj);
System.err.println( vals );
if (vals instanceof Collection<?>) {
final Collection<?> coll = (Collection<?>) vals;
Object[] array = coll.toArray(new Object[0]);
return array;
}
}
}
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException
| IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
}
}
if (obj instanceof List<?>) {
final List<?> list = (List<?>) obj;
Object[] array = list.toArray(new Object[0]);
return array;
}
return obj;
}
}
JavaScript file « StringSplit.js
// var str = 'angular.1.5.6.js', separator = ".";
function splitasJavaArray( str ) {
var result = str.replace(/\.([^.]+)$/, ':$1').split(':');
print('Regex Split : ', result);
var JavaArray = Java.to(result, "java.lang.String[]");
return JavaArray;
// return result;
}
function splitasJavaScriptArray( str, separator) {
var arr = str.split( separator ); // Split the string using dot as separator
var lastVal = arr.pop(); // remove from the end
var firstVal = arr.shift(); // remove from the front
var middleVal = arr.join( separator ); // Re-join the remaining substrings
var mainArr = new Array();
mainArr.push( firstVal ); // add to the end
mainArr.push( middleVal );
mainArr.push( lastVal );
return mainArr;
}
var objfile = new Object();
objfile.hello = function(name) { print('File : Hello, ' + name); }
JavaScript Array constructor or array literal.
With Guava:
final Splitter splitter = Splitter.on("-").trimResults();
assertEquals("Günnewig Uebachs", Iterables.getLast(splitter.split(one)));
assertEquals("Madison", Iterables.getLast(splitter.split(two)));
Splitter, Iterables
Since he was asking to do it all in the same line using split so i suggest this:
lastone = one.split("-")[(one.split("-")).length -1]
I always avoid defining new variables as far as I can, and I find it a very good practice
You mean you don't know the sizes of the arrays at compile-time? At run-time they could be found by the value of lastone.length and lastwo.length .
Also you can use java.util.ArrayDeque
String last = new ArrayDeque<>(Arrays.asList("1-2".split("-"))).getLast();
In java 8
String lastItem = Stream.of(str.split("-")).reduce((first,last)->last).get();
I guess you want to do this in i line. It is possible (a bit of juggling though =^)
new StringBuilder(new StringBuilder("Düsseldorf - Zentrum - Günnewig Uebachs").reverse().toString().split(" - ")[0]).reverse()
tadaa, one line -> the result you want (if you split on " - " (space minus space) instead of only "-" (minus) you will loose the annoying space before the partition too =^) so "Günnewig Uebachs" instead of " Günnewig Uebachs" (with a space as first character)
Nice extra -> no need for extra JAR files in the lib folder so you can keep your application light weight.