106
\$\begingroup\$

Are there any useful shortcuts that can be used in Java?

As shown below, import already adds at least 17 characters to a program.

import java.io.*;

I understand that the simple solution would be to use another language, but it seems to be a real challenge to shorten Java programs.


Tips should be specific to Java: if they're applicable to most C-like languages, they belong in the more general list of tips.

\$\endgroup\$
7
  • 10
    \$\begingroup\$ package can be skipped. \$\endgroup\$
    – st0le
    Commented Jul 19, 2012 at 7:08
  • 1
    \$\begingroup\$ In an answer, can't I just omit the imports assuming they are there? \$\endgroup\$
    – Fabricio
    Commented May 8, 2014 at 15:24
  • 37
    \$\begingroup\$ Best tip about golfing Java: don't use it. ;) \$\endgroup\$ Commented Sep 25, 2015 at 19:10
  • 4
    \$\begingroup\$ "I want to golf in java" good luck \$\endgroup\$
    – sagiksp
    Commented May 4, 2017 at 7:11
  • 3
    \$\begingroup\$ JAVA 11: make use of the "var" type inference \$\endgroup\$ Commented Nov 9, 2019 at 18:09

39 Answers 39

1
2
5
\$\begingroup\$

In most cases, your program will be single-threaded, i.e it'll have only one thread running. You can exploit this fact by returning from the main method when you have to exit instantly.

static void main(String[]a){if(condition)return;}

Compare it to "properly" terminating the program:

static void main(String[]a){if(condition)System.exit(0);}

Or pointing to null:

static void main(String[]a){if(condition)throw null;}

Or dividing by 0:

static void main(String[]a){if(condition)int A=1/0;}
\$\endgroup\$
5
\$\begingroup\$

Sometimes, a single for-loop statement might be replaceable. Consider the following code:

int m(int x){int i=1;for(;x%++i==0;);return i;}

This is a simple for-loop which is a solution to this question.

Since we know that i will not be large enough to cause StackOverflow errors, we can replace the for-loop with recursion instead:

int m(int x,int i){return x%++i>0?i:m(x,i);}

We can simulate a loop by using a ternary operator in the return statement to cause recursion.

This reduction is rather specific, but I can imagine more situations where this would come in handy.

\$\endgroup\$
5
\$\begingroup\$

Using ... (varags) as parameter

In some cases it's shorter to use a Java varargs as parameter instead of loose ones.
For example:

// Example input/output: 5, 4, 3 -> 60000
int calculateVolumeInLiters(int width, int height, int depth){
  return width * height * depth * 1000;
}

Would be golfed by most to this:

int c(int w,int h,int d){return w*h*d*1000;} // 44 bytes

But can be golfed an additional byte to this:

int c(int...a){return a[0]*a[1]*a[2]*1000;}  // 43 bytes

Note that all three integers are only accessed once in the method itself. Since int is pretty short it is only beneficial if you use them each only once inside the method, and have three or more of them as parameter.

With longer parameters this is usually more useful though. For example, this was my original answer for this challenge (calculate occurances of input character in input string):

// Example input/output: tttggloyoi, t -> 3

int c(String a,char b){return a.replaceAll("[^"+b+"]","").length();} // 68 bytes

And I was recommended to golf it to this:

int c(String a,char b){return a.split(b+"").length-1;}               // 54 bytes

But I ended up golfing it to this using ...:

int c(String...a){return a[0].split(a[1]).length-1;}                 // 52 bytes

NOTE: If the question/challenge asks for a flexible input, the ... can be shortened to [] of course. If the question/challenge specifically asks for, let's say, three String inputs and disallows an String-array containing three values, you can use String... instead of String a,String b,String c.

\$\endgroup\$
2
  • 3
    \$\begingroup\$ Can't you use a String[] instead of using varargs? (saves 1 more byte) \$\endgroup\$
    – user41805
    Commented Mar 24, 2017 at 8:13
  • \$\begingroup\$ @KritixiLithos Hmm.. good point. But that mainly depends on how flexible the input is for the challenge. If any input format is allowed, than that would indeed be shorter. I'll add this to this tips, thanks. \$\endgroup\$ Commented Mar 24, 2017 at 8:24
5
\$\begingroup\$

If you use Java 8, then you can:

Replace Lambda expressions with method references

Lambda expressions can be replaced with method references. Method reference has following form:

ClassName::methodName

so if you use one letter names for classes it's shorter then lambda. Here are the rules

lambda form                  |  reference method form
-------------------------------------------------------------------------------------------------
p -> ClassName.methodName(p) |  ClassName::methodName
p -> new ClassName(p)        |  ClassName::new
p -> p.methodName()          |  ClassName::methodName // where ClassName is class of object p
(p, q) -> p.methodName(q)    |  ClassName::methodName // where ClassName is class of object p

Examples (respectivly):

lambda                       |  reference method
-------------------------------------------------------------------------------------------------
p -> System.out.println(p)   |  System.out::println
p -> new HashSet<>(p)        |  HashSet::new
p -> p.getName()             |  Beer::getName 
(p, q) -> p.compareTo(q)     |  String::compareTo

So, if ClassName is "C", then we have following length diffs:

lambda form                  |  reference method form | length diff
-----------------------------------------------------------------------
p->C.methodName(p)           |  C::methodName         | 5 bytes
p->new C(p)                  |  C::new                | 5 bytes
p->p.methodName()            |  C::methodName         | 4 bytes
(p,q)->p.methodName(q)       |  C::methodName         | 9 bytes

Simplify lambda expressions

And here are some rules of simplifying lambda expressions.

General form of lambda expression is

(parameters) -> { statements;}  // (String a, String b) -> {return a.compareTo(b);}

When there is only one expresion, it can be simplified as follows (return should me ommitted):

(parameters) -> expression      // (String a, String b) -> a.compareTo(b)

When type declaration can be ommited, it can be simplified as follows:

(parameters) -> expression      // (a, b) -> a.compareTo(b)

When there is only one parameter and there is no need to declare type, it can be simplified as follows:

parameter -> expression         // (String s) -> System.out.printout(s)
                                // to
                                // s -> System.out.println(s)
\$\endgroup\$
3
\$\begingroup\$

Use String#isEmpty()

To check if a String is empty, you could use either of these:

s.length()<1  // 12 bytes
s.equals("")  // 12 bytes

However, using .isEmpty() is one byte shorter:

s.isEmpty()   // 11 bytes

Note that for Lists it's still shorter to check the size instead of using isEmpty():

l.size()<1    // 10 bytes
l.isEmpty()   // 11 bytes
\$\endgroup\$
5
  • 1
    \$\begingroup\$ I don't really know Java that well but can't you just use s=="" \$\endgroup\$
    – jdt
    Commented May 4, 2017 at 15:28
  • 2
    \$\begingroup\$ @JohanduToit In Java unfortunately not. String is an Object, and since Java is passed-by-reference, s and "" doesn't point to the same reference, even if they have the same value. So new String("test") == "test" returns false, and new String("test").equals("test") returns true. String literals are an exception to this rule, so "test" == "test" will return true, because the compiler references to the same spot in the background. Perhaps better explained here or .equals in general here \$\endgroup\$ Commented May 4, 2017 at 18:09
  • \$\begingroup\$ @JohanduToit You could do s.intern()=="" to force Java to replace it with the equivalent object from the string pool, but that's 14 bytes, not really an improvement over the other methods. \$\endgroup\$ Commented Feb 14, 2018 at 20:44
  • \$\begingroup\$ @KevinCruijssen [...] since Java is passed-by-reference [...] -- more importantly since Java does not allow operator overloading and defines equality as identity. \$\endgroup\$ Commented Sep 26, 2018 at 14:26
  • \$\begingroup\$ actually, interesting enough, you can use s=="" if you make s="' at first, see my fizz buzz java program for an example codegolf.stackexchange.com/questions/58615/1-2-fizz-4-buzz/… I love how my ide says that s=="" doesn't work, but I can run the program just fine \$\endgroup\$ Commented Feb 2, 2021 at 18:05
3
\$\begingroup\$

Bit twiddling actions

Swap variables

You might want to swap int and long variables. The usual way is to have a temporary variable:

void swap(int a, int b) {
  int t=a;a=b;b=t;     //  16 bytes
  System.out.printf("a=%d, b=%d%n", a, b);
}

But you can shorten it like this:

void swap(int a, int b) {
  a^=b^(b=a);          // 11 bytes
  System.out.printf("a=%d, b=%d%n", a, b);
}

Even if you reuse a temporary variable, it's just shorter to write that code, no matter the length of each variable name.

Does work with short and byte but at the cost of casting.

Swap the variables so that the min is in a specific variable and the max is in the other

You have a and b and you don't know which is greater. But you want a to contain the lowest and b to contain the greatest.

void swapMinMax(int a, int b) {
  a^=b<a?b^(b=a):0;            // 17 bytes
  System.out.printf("a=%d, b=%d%n", a, b);
}
\$\endgroup\$
1
\$\begingroup\$

Sometimes, you can use lambdas with iterators:

// SUBOPTIMAL: Don't use lambdas here!
Iterator<A>i=a.iterator();for(A x:(Iterable<A>)()->i){if(x==y)break;}return i.hasNext()?i.next():null;
Iterator<A>i=a.iterator();for(;i.hasNext();){if(i.next()==y)break;}return i.hasNext()?i.next():null;
Iterator<A>i=a.iterator();while(i.hasNext()){if(i.next()==y)break;}return i.hasNext()?i.next():null;

// Lambdas save 11 bytes here!
Iterator<A>i=a.iterator();Iterable<A>j=()->i;for(A x:j){if(x==y)break;}for(A x:j){if(x==z)break;}return i.hasNext()?i.next():null;
Iterator<A>i=a.iterator();for(;i.hasNext();){if(i.next()==y)break;}for(;i.hasNext();){if(i.next()==z)break;}return i.hasNext()?i.next():null;
Iterator<A>i=a.iterator();while(i.hasNext()){if(i.next()==y)break;}while(i.hasNext()){if(i.next()==z)break;}return i.hasNext()?i.next():null;
\$\endgroup\$
1
\$\begingroup\$

Use Try it online to share lambdas

If the solution can be writen in a lambda, Try it online can help you format and reduce what characters need to be included in the solution.

See this for an example.

\$\endgroup\$
0
\$\begingroup\$

Convert number to string

It may seem obvious, you can shorten your code by adding the number to "":

// int a = 123
Integer.toString(a) // 0
String.valueOf(a)   // -2 chars
"".valueOf(a)       // -6 chars
(""+a)              // -13 chars
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.