173

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 :(

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
n00ki3
  • 14,529
  • 18
  • 56
  • 65

12 Answers12

316

You could use lastIndexOf() method on String

String last = string.substring(string.lastIndexOf('-') + 1);
Denis Bazhenov
  • 9,680
  • 8
  • 43
  • 65
  • 17
    i think this solution takes less resources. – ufk May 26 '10 at 15:32
  • 1
    Won't this throw an `IndexOutOfBoundsException` if `string` does not contain `'-'`? – Jared Beck Sep 02 '13 at 23:01
  • 7
    No, @JaredBeck, it doesn't. But it does return the entire string, which may or may not be want you want. Might be better to check that the character you're splitting on exists in the string first. – james.garriss Dec 06 '13 at 18:10
  • 1
    I see, `lastIndexOf` returns `-1`. So that's what the `+ 1` is for. Kind of cryptic to a Java novice like me. – Jared Beck Dec 06 '13 at 23:04
  • 2
    But that will throw an `IndexOutOfBoundsException` if `string` contains `'-'` at the last position – damgad Apr 16 '14 at 10:02
  • 9
    @damgad, it won't. lastIndexOf will be length of the string - 1. So, you will end up with the empty string – Denis Bazhenov May 01 '15 at 02:41
  • I believe that considering the example given, `trim` should be applied also to remove the trailing whitespace: `String last = string.substring(string.lastIndexOf('-') + 1).trim();` – acoelhosantos Jan 26 '17 at 17:54
  • The point is that you have to feed the same string twice into this expression or create a new method for it. Pity that there seems to be no way of extracting the last part without this. Other languages perform better here. set last [lindex [split $string .] end] – Holger Jakobs Feb 06 '19 at 11:09
  • 1
    Without using 3rd party libraries this seems to be the most robust solution. Example on how it never throws an IndexOutOfBoundsException: https://onlinegdb.com/H1VoX1MbU – Dário Jan 19 '20 at 14:15
206

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

Dário
  • 2,002
  • 1
  • 18
  • 28
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 28
    Just be aware that in the case where the input string is empty, the second statement will throw an "index out of bounds" exception. – Stephen C Jul 26 '09 at 01:23
  • 8
    no it wont, of you split an empty string it will return an array containing an one element which is the empty string itself. – Panthro Jul 27 '17 at 18:45
  • 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 – Dário Jan 17 '20 at 08:25
  • See Denis Bazhenov answer for a solution that doesn't throw ArrayIndexOutOfBoundsException: https://stackoverflow.com/a/1181976/4249576 – Dário Jan 19 '20 at 14:16
52

You can use the StringUtils class in Apache Commons:

StringUtils.substringAfterLast(one, "-");
Ranosama
  • 639
  • 5
  • 10
  • 1
    Please be aware that this will not work in cases where there is no "-". The result will be blank instead of the eventually expected String (one). – zyexal Sep 22 '22 at 09:03
  • @zyexal Good point. Denis Bazhenov's answer doesn't have this caveat so that would probably be a better option in most use cases. It also doesn't add a 3rd party dependency, which is always nice. – Ranosama Oct 26 '22 at 12:52
23

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("-"));
dfa
  • 114,442
  • 31
  • 189
  • 228
  • 3
    One thing you should do is protect last() method against empty arrays or you could get IndexOutOfBoundsException. – Denis Bazhenov Jul 25 '09 at 12:12
  • @dotsid, On the other hand it might be better to throw an ArrayIndexOutOfBoundsException rather than return null here, since you'll catch the error where it occurs rather when it causes the problem. – Emil H Jul 25 '09 at 12:15
  • 1
    @dotsid, I would leave this responsibility to the caller, hiding runtime exceptions is dangerous – dfa Jul 25 '09 at 12:27
  • Very nice, and of course `first()` and `nth(T[array], int n)` is nicely made from this. – Peter Ajtai Apr 13 '12 at 22:11
16
String str = "www.anywebsite.com/folder/subfolder/directory";
int index = str.lastIndexOf('/');
String lastString = str.substring(index +1);

Now lastString has the value "directory"

buræquete
  • 14,226
  • 4
  • 44
  • 89
Zar E Ahmer
  • 33,936
  • 20
  • 234
  • 300
15

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);

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); }
Yash
  • 9,250
  • 2
  • 69
  • 74
  • Attention when using Java 8 Stream example. if you split by space (" ") a String like this: `Basic `(there is a trailing space), you will get `Basic` as the the last element. – belgoros Sep 18 '18 at 09:15
7

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

palacsint
  • 28,416
  • 10
  • 82
  • 109
5

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

azerafati
  • 18,215
  • 7
  • 67
  • 72
3

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 .

dfa
  • 114,442
  • 31
  • 189
  • 228
Sean A.O. Harney
  • 23,901
  • 4
  • 30
  • 30
3

Also you can use java.util.ArrayDeque

String last = new ArrayDeque<>(Arrays.asList("1-2".split("-"))).getLast();
3

In java 8

String lastItem = Stream.of(str.split("-")).reduce((first,last)->last).get();
Hadi J
  • 16,989
  • 4
  • 36
  • 62
1

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.

irJvV
  • 892
  • 8
  • 26