This depends on your definition of concise, I suppose. Here's a bit of Java 8 Stream capability that does what you want, in a similar way to your JS code, and is arguably somewhat concise.
int[] arr = {1, 2, 3, 4, 5};
int k = 4;
String result = Arrays.stream(arr).skip(k).mapToObj(Integer::toString).collect(Collectors.joining(" ")) + " " + Arrays.stream(arr).limit(k).mapToObj(Integer::toString).collect(Collectors.joining(" "));
To break down what each bit does:
Arrays.stream(arr) just creates a Stream of ints (Specifically, an IntStream, since int, as a built-in type, must have its own wrapper stream class rather than the generic Stream<T>).
skip(k) essentially discards as many elements as the provided input, so we can start with the part from the index forward.
mapToObj(Integer::toString) is how we convert the Stream from an IntStream to a Stream<String>, so that we can join it into a single String. It takes each element in the Stream and applies the Integer.toString method to it, i.e. if each element of the Stream were in turn referred to as int, it would be like calling Integer.toString(int). We are now left with a Stream of Strings representing the numbers.
collect(Collectors.joining(" ")) takes each value, and gives it to a Collector. Collectors take Streams and reduce them to single objects. In this case, the joining Collector takes each object and joins them all to a single string, and the argument we have provided is the delimiter it uses.
- Looking at the second half of the procedure, the only really different part is
limit(k), which simply takes the first k elements of the Stream and ignores the rest.
It's a bit more long-winded that your JS example (necessary partly because of Java's strong typing and partly because Java arrays aren't objects and therefore don't do anything useful by themselves), but fairly easy to understand and very powerful.