在Java中是否可以使用任何有用的快捷方式?
如下所示,import
已经在程序中添加了至少17个字符。
import java.io.*;
我知道简单的解决方案是使用另一种语言,但是缩短Java程序似乎是一个真正的挑战。
提示应特定于Java:如果它们适用于大多数类似C的语言,则它们属于更一般的提示列表。
在Java中是否可以使用任何有用的快捷方式?
如下所示,import
已经在程序中添加了至少17个字符。
import java.io.*;
我知道简单的解决方案是使用另一种语言,但是缩短Java程序似乎是一个真正的挑战。
提示应特定于Java:如果它们适用于大多数类似C的语言,则它们属于更一般的提示列表。
Answers:
使用最新的Java。Java 8允许您使用lambda表达式,因此,即使您需要诸如函数对象之类的东西,也可以使用它。
为您经常使用的东西定义缩短的功能。例如,您有100个调用exampleClassInstance.doSomething(someParameter)
,定义了一个新函数void d(ParameterType p){exampleClassInstance.doSomething(p)}
并使用它来保存一些字符。
如果您多次使用特定的长类名称,例如
MyEventHandlerProxyQueueExecutorServiceCollectionAccessManagerFactory
而是定义一个新类:
class X extends MyEventHandlerProxyQueueExecutorServiceCollectionAccessManagerFactory{}
如果仅使用该类的一种特定方法(但仍需要实例化),则可以在新类中同时定义一个缩短的版本。
在可能的情况下,使用函数类型参数来缩短内容,例如:
<T>void p(T o){System.out.println(o);}
使用for(;;)
代替while(true)
。
除非绝对必要,否则请勿使用访问修饰符。
请勿final
用于任何用途。
切勿在for
循环后放置一个块(但是foreach循环for(x:y)
是不同的)。其他语句应放在for
语句本身之内,例如for(int i=0;i<m;a(i),b(++i))c(i);
。
使用内联分配,增量,实例化。在适当的地方使用匿名内联类。如果可能,请改用lambda。嵌套函数调用。某些函数可以保证返回其父对象,而实际上这些函数甚至意味着要链接在一起。
您的main
方法throws Exception
是,而不是抓住它们。
Error
比短Exception
。如果出于某种原因您确实需要向throw
堆栈发送消息,请使用Error
,即使这是完全正常的情况。
如果某些情况需要立即终止,请使用int a=1/0;
而不是throw null;
或System.exit(0);
。在运行时,这将引发一个ArithmeticException
。如果您的代码中已有数字变量,请改用它。(如果已经拥有import static java.lang.System.*;
,请继续exit(0);
。)
代替实现类似的接口,List<E>
扩展一个立即子级(或完全不那么直接,如果这样做有任何好处)的子类,例如AbstractList<E>
,它提供大多数方法的默认实现,并且仅需要实现一些关键部分。
首先用换行符,缩进和完整的变量名长写地编写代码。一旦有了有效的代码,就可以缩短名称,四处移动声明并添加快捷方式。通过长期编写出来,您将有更多机会简化整个程序。
将替代性优化与一段代码进行比较,因为通过对代码进行很小的更改,最优化的策略就会发生巨大变化。例如:
Arrays.sort(a)
,则最有效的方法是使用完全限定的名称进行调用java.util.Arrays.sort(a)
。void s(int[]a){java.util.Arrays.sort(a);}
。在这种情况下,它仍应使用标准名称。(如果需要多个重载,则可能做错了。)for
在打高尔夫球时使用短循环,而在缺少易于访问的库方法的情况下完成),则可以利用它Arrays.copyOf
来完成任务。如果使用多个方法,并且有3个或更多调用,则执行import static java.util.Arrays.*;
是引用这些方法的最有效方法。之后,仅当您有8个以上的单独呼叫时,才sort
应为其使用快捷方式方法,并且仅在5个或更多呼叫时才保证使用快捷方式copyOf
。对代码执行这种分析的唯一真实方法是对代码的副本进行实际的修改,然后比较结果。
避免使用someTypeValue.toString();
method,而是追加append someTypeValue+""
。
如果确实需要Windows,请不要使用Swing,而应使用AWT(除非您确实需要Swing中的功能)。比较import javax.swing.*;
和import java.awt.*;
。此外,在Swing组件都有一个J
前缀,以他们的名字(JFrame
,JLabel
,等),但在AWT组件不(Frame
,Label
,等)
使用interface
代替class
。
在Java 8中,将静态方法添加到接口。在接口中,默认情况下所有方法都是公共的。所以
class A{public static void main(String[]a){}}
现在可以缩短为
interface A{static void main(String[]a){}}
这显然更短。
例如,我在“ Hello,World!”中使用了此功能。挑战。
使用静态导入:
import static java.lang.System.out;
// even shorter (thanks to Johannes Kuhn):
import static java.lang.System.*;
您可以稍后保存一些样板,但需要多次调用才能获得收益:
public static void main (String[] args) {
out.println ("foo");
out.println ("bar");
out.println ("baz");
}
Java
!
import static java.lang.System.*
。
var o=System.out;
这一点,只需要使用两次就可以了
var o=System.out.println
工作吗?
如果必须使用布尔表达式true
或false
,请分别用1>0
和替换它们1<0
。
例如:
boolean found=false;
for(i=0; i<10; i++) if(a[i]==42) found=true;
该线性搜索示例可以简化为
boolean f=1<0;
for(i=0;i<10;)if(a[i++]==42)f=1>0;
true/false
,只需添加boolean t=1>0,f=1<0;
。然后,而不是1>0
使用t
和保存每次使用两个字符。支付1>0
方式有10种用途。
boolean t=1>0,f=!t;
-缩短一个字符!
true
/ 以及其他许多(!)false
:f|=a[i++]==42;
节省很多。
boolean
,但是由于在撰写本文时无法提供任何示例(我通常不使用Java代码),所以我只写了一个简单的示例。
如果您将大量使用某些方法,请将其常驻类分配给变量。例如,分配System.out
给变量:
java.io.PrintStream o=System.out;
//now I can call o.print() or o.println() to the same effect as System.out.println()
也适用于Integer.parseInt()
:
Integer i=1;
i.parseInt("some string");
这几乎肯定会触发有关“从变量访问静态方法”的思想警告。
((Integer)1).parseInt("1")
也可以。
new Integer("1")
甚至更短。但是贾斯汀对他的回答的意思是,您可以将已经拥有的变量重用于静态调用。正如我在此答案底部所解释的。
如果您需要从参数(或任何其他字符串)中获取数字,通常会看到类似以下内容的内容:
public static void main(String[]a){
int n=Integer.valueOf(a[0]);
...
}
很多时候,你并不需要的Integer
。很多挑战不会大量使用。由于Short
和Byte
都将取消装箱到int
,请改用更合适的方法,valueOf()
并节省几个字节。
不过,请保留您的实际变量为int
,因为它比byte
和都短short
:
int n=Byte.valueOf(a[0]);
如果您需要对多个数字执行此操作,则可以与以下方法结合使用:
Byte b=1;
int n=b.valueOf(a[0]),m=b.valueOf(a[1])...
int n=new Byte(a[0]);
是三个短。如果数字可能更大,请使用long n=new Long(a[0])
,int
在大多数情况下,它仍比s 更好。
不要使用public class
。main方法需要是公共的,但它的类不需要。此代码有效:
class S{public static void main(String[]a){System.out.println("works");}}
java S
即使class S
不是公开课,您也可以参加比赛。(更新:撰写本文时,我正在使用Java7。在Java 8中,您的主要方法应该在接口中。在Java 5或6中,您的主要方法应该在枚举中。)
很多Java程序员都不知道这一点!关于非公共类中的main 的Stack Overflow问题的大约一半答案错误地声称main方法必须在公共类中。现在您知道了。删除public
in public class
并保存7个字符。
interface s{static void main(String[]...
会更短。如果必须具有可编译的源文件和main方法。因为在Java 1.8接口中,所有方法都是公共的,所以您可以跳过方法上的修饰符。
这些技巧对于单独的答案来说有点太小了,因此我将把这个答案用于我发现或想出的非常小的代码高尔夫技巧,而其他技巧尚未提及:
// I used to do something like this:
s.substring(0,s.length()-1) // 27 bytes
// But this is shorter:
s.replaceAll(".$","") // 21 bytes
在某些情况下,您事先知道最后一个字符是什么,并且您也知道此字符在字符串中仅出现一次。在这种情况下,您可以.split
改用:
// As example: "100%" to "100"
s.split("%")[0] // 15 bytes
// When you want to get the UTF-8 bytes I used to do this:
s.getBytes("UTF-8"); // 20 bytes
// But you can also use "UTF8" for the same result:
s.getBytes("UTF8"); // 19 bytes
所有编码都有java.nio
API中使用的规范名称,以及java.io
和java.lang
API中使用的规范名称。这是Java中所有受支持的编码的完整列表。因此,请始终使用两者中最短的一个。第二个通常较短(如UTF-8
vs utf8
,Windows-1252
vs Cp1252
等),但并不总是较短(UTF-16BE
vs UnicodeBigUnmarked
)。
// You could do something like this:
new java.util.Random().nextBoolean() // 36 bytes
// But as mentioned before in @Geobits' answer, Math.random() doesn't require an import:
Math.random()<.5 // 16 bytes
检查素数或获得所有素数的方法有很多,但是@SaraJ的答案是最短的。以下是复制粘贴作为参考:
// Check if n is a prime:
n->{int i=1;for(;n%++i%n>0;);return n==i;}
// Which can easily be modified to loop through primes:
v->{for(int n=2,i;;){for(i=1;n%++i%n>0;);if(n++==i)/*do something with prime `i` here*/;}}
注意:通常,您可以根据要使用的方式将其与其他现有循环合并,因此不需要单独的方法。例如,这在此答案中节省了大量字节。
如果您要使用正双精度数/浮点数并且想要使用floor
它们,请不要使用Math.floor
而是使用(int)
-cast(因为Java在整数上截断):
double d = 54.99;
int n=(int)Math.floor(d); // 25 bytes
int m=(int)d; // 13 bytes
// Outputs 54 for both
可以将相同的技巧应用于负双打/浮动,ceil
而不是:
double d = -54.99;
int n=(int)Math.ceil(d); // 24 bytes
int m=(int)d; // 13 bytes
// Outputs -54 for both
&1
代替%2
来消除括号:由于运算符优先级的&
比默认的算术运算符类似的低级*/+-
和%
,你可以摆脱在某些情况下的括号。
// So instead of this:
(i+j)%2 // 7 bytes
// Use this:
i+j&1 // 5 bytes
请注意,这在布尔检查中并没有真正的帮助,因为那时您仍然需要括号,它们只是稍微移动了一点:
(i+j)%2<1 // 9 bytes
(i+j&1)<1 // 9 bytes
使用BigIntegers时,只需创建一次即可,然后可以重复使用。正如你可能知道,BigInteger的包含静态字段ZERO
,ONE
和TEN
。因此,当您仅使用这三个时,就不需要使用,import
而是可以java.Math.BigInteger
直接使用。
// So instead of this:
import java.math.BigInteger.*;
BigInteger a=BigInteger.ONE,b=BigInteger.ZERO; // 76 bytes
// or this:
java.math.BigInteger a=java.math.BigInteger.ONE,b=a.ZERO; // 57 bytes
// Use this:
java.math.BigInteger t=null,a=t.ONE,b=t.ZERO; // 45 bytes
注意:您必须使用=null
so t
进行初始化才能使用t.
。
有时,您可以添加多个BigIntegers来创建另一个以节省字节。因此,假设您1,10,12
出于某种原因希望拥有BigIntegers :
// So instead of this:
BigInteger t=null,a=t.ONE,b=t.TEN,c=new BigInteger(12); // 55 bytes
// Use this:
BigInteger t=null,a=t.ONE,b=t.TEN,c=b.add(a).add(a); // 52 bytes
正如注释中正确指出的那样,BigInteger t=null;
静态方法调用的技巧也可以与其他类一起使用。
例如,以下是2011年的答案:
// 173 bytes:
import java.util.*;class g{public static void main(String[]p){String[]a=p[0].split(""),b=p[1].split("");Arrays.sort(a);Arrays.sort(b);System.out.print(Arrays.equals(a,b));}}
// 163 bytes
class g{public static void main(String[]p){java.util.Arrays x=null;String[]a=p[0].split(""),b=p[1].split("");x.sort(a);x.sort(b);System.out.print(x.equals(a,b));}}
getBytes()
代替 toCharArray()
当您想遍历字符串的字符时,通常会这样做:
for(char c:s.toCharArray()) // 27 bytes
// or this:
for(String c:s.split("")) // 25 bytes
在打印字符或将其附加到字符串或类似内容时,循环遍历字符可能很有用。
但是,如果你只使用一些Unicode的数量计算的字符,你可以替换char
使用int
,并且可以替换toCharArray()
使用getBytes()
:
for(int c:s.getBytes()) // 23 bytes
甚至在Java 8+中更短:
s.chars().forEach(c->...) // 22 bytes
在Java 10+中,现在可以以22个字节为单位循环打印字符:
for(var c:s.split("")) // 22 bytes
List
:List l=...;
// When we have an `import java.util.*;` in our code, shuffling is shortest:
return l.get(new Random().nextInt(l.size())); // 45 bytes
return l.get((int)(Math.random()*l.size())); // 44 bytes
Collections.shuffle(l);return l.get(0); // 39 bytes
// When we don't have an `import java.util.*` in our code, `Math.random` is shortest:
return l.get(new java.util.Random().nextInt(l.size())); // 55 bytes
return l.get((int)(Math.random()*l.size())); // 44 bytes
java.util.Collections.shuffle(l);return l.get(0); // 49 bytes
String s=...;
// I used to use a regex like this:
s.matches(" .*|.* ") // 20 bytes
// But this is shorter:
!s.trim().equals(s) // 19 bytes
// And this is even shorter due to a nice feature of String#trim:
s!=s.trim() // 11 bytes
当!=
在Strings上检查引用而不是Java中的值时,为什么这样做有效?因为String#trim
将返回“ 此字符串的副本,其中删除了前导和尾随空白,如果没有前导或尾随空白,则返回此字符串。 ”在有人向我建议之后,在我的这个答案中,我使用了它。
要检查一个字符串是否是回文(记住字符串的偶数和奇数长度),这是最短的(.contains
在这里起作用,因为我们知道字符串本身及其反向形式的长度是相等的):
String s=...;
s.contains(new StringBuffer(s).reverse()) // 41 bytes
.contains(...)
而不是.equals(...+"")
感谢@assylias在这里的评论。
我想大多数已经知道这一个:如果您要检查如果任一a
或者b
是零,而不是乘救字节:
a==0|b==0 // 9 bytes
a*b==0 // 6 bytes
而且,如果要检查两个a
和b
是否均为零,则可以使用按位或,或者如果它们始终为正,则将它们加在一起:
a==0&b==0 // 9 bytes
(a|b)==0 // 8 bytes (if either `a`, `b` or both can be negative)
a+b<1 // 5 bytes (this only works if neither `a` nor `b` can be negative)
// even = 1; odd = -1:
n%2<1?1:-1 // 10 bytes
1-n%2*2 // 7 bytes
// even = -1; odd = 1:
n%2<1?-1:1 // 10 bytes
n%2*2-1 // 7 bytes
我添加这个的原因是k+(k%2<1?1:-1)
在这个答案中看到之后:
k+(k%2<1?1:-1) // 14 bytes
// This would already have been shorter:
k%2<1?k+1:k-1 // 13 bytes
// But it can also be:
k%2*-2-~k // 9 bytes
n
完整程序中的循环时间如果在强制执行完整程序的过程中遇到挑战,并且需要循环特定的时间,则可以执行以下操作:
// instead of:
interface M{static void main(String[]a){for(int n=50;n-->0;)/*do something*/}} // 78 bytes
// we could do:
interface M{static void main(String[]a){for(M m:new M[50])/*do something*/}} // 76 bytes
当我们必须将此范围用作输入时,同样适用:
interface M{static void main(String[]a){for(int n=new Byte(a[0]);n-->0;)/*do something*/}} // 90 bytes
interface M{static void main(String[]a){for(M m:new M[new Byte(a[0])])/*do something*/}} // 88 bytes
如果您不能使用a,throws Exception
但必须catch
在返回之前对其进行处理,则可以finally
改用:
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
至于何时使用a的示例try-catch
,我可以参考我的答案(间接高尔夫球场的积分去@KamilDrakari)。在此挑战中,我们必须在NxM矩阵上对角循环,因此我们必须确定列数或行数是否为for循环中的最小值或最大值(以字节为单位,这是非常昂贵的:)i<Math.min(a.length,a[0].length)
。因此,仅捕获ArrayIndexOutOfBoundsException
使用catch-finally
情况比此检查要短,从而节省了字节:
int[] a = ...;
int r=0,i=0;for(;i<Math.min(a.length,a[0].length);)r=...i++...;return r; // 66 bytes
int r=0,i=0;try{for(;;)r=...i++...;}finally{return r;} // 48 bytes
注意:这仅是因为return r;
最后的才起作用。建议我修改第一个单元格,就像@KamilDrakari在他的C#答案中所做的那样以保存字节。但是,在Java中,这意味着我将不得不将其更改为m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}
(73个字节),实际上增加了字节数,而不是如果可以使用则减少了字节数finally
。
当您想要2的幂时,按位计算的方法要短得多:
(int)Math.pow(2,n) // 16 bytes
(1<<n) // 6 bytes
我认为这是现在众所周知的&
,并|
可以用来代替&&
和||
中爪哇(布尔)逻辑检查。在某些情况下,您仍然想使用&&
而不是&
防止错误,例如index >= 0 && array[index].doSomething
。如果&&
将更改为&
此处,它将仍然评估在数组中使用索引的部分,从而导致ArrayIndexOutOfBoundsException
,因此&&
在这种情况下使用代替&
。
到目前为止,Java 中&&
/ ||
vs &
/ 的基础知识|
。
当您想检查时(A or B) and C
,最短的似乎使用了如下的按位运算符:
(A|B)&C // 7 bytes
但是,由于按位运算符的优先级高于逻辑检查,因此您可以将两者合并以在此处保存一个字节:
A|B&&C // 6 bytes
n+=...-n
代替(long)...
例如,当使用lambda时,输入和输出中都有一个长Math.pow
字符时,可以使用n+=...-n
代替来保存一个字节(long)...
。
例如:
n->(long)Math.pow(10,n) // 23 bytes
n->n+=Math.pow(10,n)-n // 22 bytes
since Java automatically floors on integers
; 我认为适当的术语是截断,而不是地板。
String t="";for(int i=s.length();--i>=0;t+=s.charAt(i));return s.equals(t);
s.equals(new StringBuffer(s).reverse()+"")
足够了。
对于不需要输入的高尔夫,您可以使用静态块,并且无需任何主要方法就可以很好地运行它,只需使用Java 6进行编译即可。
public class StaticExample{
static {
//do stuff
}
}
java
在命令行/清单文件中告诉要加载的类来解决此问题。
您不必使用Character.toLowerCase(char c)
。改为使用(c|32)
。代替Character.toUpperCase(char c)
使用(c&~32)
。这仅适用于ASCII字母。
c|~32
往往会导致-1 ...更好地使用c-32
。
有多种将String转换为数值的方法:
String s = "12";
ABC.parseABC:
Short.parseShort(s); // 20 bytes
Integer.parseInt(s); // 20 bytes
Long.parseLong(s); // 18 bytes
ABC.valueOf:
Short.valueOf(s); // 17 bytes
Integer.valueOf(s); // 19 bytes
Long.valueOf(s); // 16 bytes
ABC.decode:
// Note: does not work for numeric values with leading zeros,
// since these will be converted to octal numbers instead
Short.decode(s); // 16 bytes
Integer.decode(s); // 18 bytes
Long.decode(s); // 15 bytes
新ABC:
new Short(s); // 13 bytes
new Integer(s); // 15 bytes
new Long(s); // 12 bytes
因此,对于代码查询,最好在将String转换为数值时使用构造函数。
同样适用于Double
; Float
; 和Byte
。
当您可以将已经存在的图元用作对象时,这并不总是适用。
例如,假设我们有以下代码:
// NOTE: Pretty bad example, because changing the short to int would probably be shorter..
// but it's just an example to get the point across
short f(short i,String s){
short r=new Short(s); // 21 bytes
... // Do something with both shorts
}
您可以.decode
通过将参数重新用作对象来代替较短的构造函数:
short f(Short i,String s){ // Note the short parameter has changed to Short here
short r=i.decode(s); // 20 bytes
... // Do something with both shorts
}
不要使用Random
!
通常,如果您需要随机数,这Random
是一种可怕的解决方法*。更好地Math.random()
代替使用。要使用Random
,您需要执行以下操作(假设我们需要一个int
):
import java.util.*;
Random r=new Random();
a=r.nextInt(9);
b=r.nextInt(9);
比较一下:
a=(int)(Math.random()*9);
b=(int)(Math.random()*9);
和:
int r(int m){return(int)(Math.random()*m);}
a=r(9);
b=r(9);
第一种方法采用41+15n
字符(n
即呼叫数)。第二个是25n
字符,第三个是43+7n
。
因此,如果只需要一次或两次,请使用内联Math.random()
方法。对于三个或更多呼叫,您将使用函数进行保存。无论是一个在保存字符第一次使用了Random
。
如果您已经在使用Math.random()
for double
,请记住,有四种用途,将其投入以下仍是一种节省:
double r(){return Math.random();}
对于33个字符,每次致电您将节省10个字符 r()
更新资料
如果您需要一个整数并希望节省转换费用,请不要进行转换!如果您执行操作而不是分配操作,则Java自动广播。相比:
a=(int)(Math.random()*9);
a=9;a*=Math.random();
* 除非您必须植入PRNG以获得可预期的结果。然后,我看不出有什么办法。
Random#nextGaussian
。
(int)(Math.random()*9)
具有很小的模偏差,因为它Math.random()
返回2 53个可能的值,而2 53不是9的倍数。每个数字的概率在1/9上下5 /(9 * 2 ** 53)之内,误差是如此之小,几乎是1/9。
9
只是作为例子,可以是任何东西。我相对确定nextInt()
(或任何其他Random
方法)也存在较小的偏差,这仅仅是由于Java的PRNG的工作方式而引起的。
new java.util.Random().nextBoolean()
可以使用代替Math.random()<.5
。
我不知道您是否会考虑使用这种“纯” Java,但是“ 处理”允许您以很少的初始设置(自动完成)来创建程序。
对于控制台输出,您可以执行以下操作:
println("hi"); //done
对于图形输出,还有一点:
void setup() {
size(640,480);
}
void draw() {
fill(255,0,0); //color used to fill shapes
rect(50,50,25,25); //25x25 pixel square at x=50,y=50
}
size
;它将默认为100 x 100像素的正方形。在大多数操作系统中,其周围的框架大约是框架的两倍,正方形居中,其余区域填充了从桌面获取的内容。
setup()
并draw()
使用“静态模式”。您还可以使用6位数的十六进制颜色,解释器将更改它们,有时会有所回报(#FF8000
< 255,128,0
),如果您使用灰度,则只需指定一个数字(255
< 255,255,255
)
您可以使用以下命令将字符串的返回语句缩短一个字节:
return "something";
至
return"something";
而且,如果您碰巧以圆括号开头的return语句,则可以对它们执行相同的操作:
return (1+taxRate)*value;
至
return(1+taxRate)*value;
我猜引号被认为是括号吗?我实际上很有趣地通过AppleScript挑选了它,并认为可能值得一提。
return-n;
代替return -n;
或return~n;
代替return ~n;
。以及单引号而不是双引号:return'A';
int
代替boolean
在某些情况下,我发现从通常会返回布尔值的方法中返回整数值要短一些,这与在C程序中执行的操作类似。
蝙蝠马上int
比短4个字节boolean
。每次写入return 0
而不是写入时return 1<0
,都将额外保存2个字节,并且在return 1
over处保持相同return 1>0
。
这里的陷阱是,每次您想直接将返回值用作布尔值时,它都要花费2个字节(if(p(n))
v。if(p(n)>0)
)。这可以通过使用布尔算术来弥补。给定一个想要编写的场景
void a(int[]t){t[0]+=p(n)?10:0;}
你可以改写
void a(int[]t){t[0]+=p(n)*10;}
为了节省2个字节。
0
并且1
不构成虚假/真正在Java中(和JLS没有任何考虑他们的方式)。因此,如果高尔夫专门要求真假,则需要对它进行布尔化(不幸的是,将其设置为boolean
函数,并向其抛出更多字节)。
t[0]+=p(n):10?0;
这甚至有效吗?
t[0]+=p(n)?10:0;
。(我对其进行了编辑。)
如果使用enum而不是class,则保存一个字符。
enum NoClass {
F, G, H;
public static void main (String[] args) {
}
}
但是您必须引入至少一个枚举实例(在此示例中为F,G,H),这些实例必须自己偿还。
enum M{;public static void main(String[]a){...}
没有问题。
class M{
与的长度完全相同enum M{;
。在那种情况下,我会选择class
因为它更漂亮(IMO)
enum{
工作没有;
时间;它唯一的IDE抱怨有错误,但编译器接受它
当您具有应返回boolean
或的方法时Boolean
,即:
// Return true if the (non-negative) input is dividable by 5
boolean c(int i){return i%5<1;}
您可以将boolean
/ Boolean
return-type更改Object
为保存1个字节:
Object c(int i){return i%5<1;}
另外,您可能已经注意到,可以使用<1
检查而不是==0
保存字节。尽管这是通用的代码技巧,而不是特定于Java的技巧。
这通常在整数不能为负数时使用,例如检查长度:
a.length<1
代替
a.length==0
c(-21)
返回true
。
c(-20)
不是要代替-21
吗?-21 % 5 = 4
和-20 % 5 = 0
。
%
,所以我忘了的Java返回余数,而不是模量,因此..区别
StringBuilder
s将内容附加到String
占用更少的字节。
// s is a StringBuilder
s.append("Hello, World!");
// S is a String
S+="Hello, World!";
如果必须反转字符串并立即打印,请使用StringBuffer
。
System.out.print(new StringBuilder("Hello, World!").reverse());
System.out.print(new StringBuffer("Hello, World!").reverse()); // Note that you can omit toString() when printing a non-String object
如果您必须反转字符串然后执行除打印字符串以外的其他操作,请使用for
each循环。
String b=new StringBuffer("Hello, World!").reverse().toString();
String B="";for(String c:"Hello, World!".split(""))B=c+B;
StringBuffer
反向字符串短。String b="";for(char c:"Hello, World!".toCharArray()){b=c+b;}
{}
如果要使用该方法,还应该从该foreach循环中删除。
String s:"".split("")
代替节省2个字节char c:"".toCharArray()
。
java.util.stream.Stream
已经导入,并且需要将另一个调用链接到结果(如B.chartAt(42)
),或者只需要将结果传递给函数(如f(B)
),则使用for(:)
equall即可Stream.of("Hello, World!".split("")).reduce("",(a,b)->b+a)
。
String b=new StringBuffer("Hello, World!").reverse()+"";
(.toString
替换为+""
),和您的第二线可以变成:String B="";for(String c:"Hello, World!".split(""))B=c+B;
(char
到String
和.toCharArray()
到.split("")
)。
var
如果定义特定类型的单个变量,请使用var
。
var i=0; // int
var l=0L; // long
var s=""; // String
var a=new int[]{1,2,3}; // int[]
var i=java.math.BigInteger.ONE; // BigInteger
var m=new java.util.HashMap(); // HashMap
var i=3+"abc".length() // int
var a="a b c".split(" "); // String[]
for(var a:"a b c".split(" ")) // String
var
不能在许多示例中使用
var i=1,j=2; // only one variable is accepted at a time
var a={1,2,3}; // arrays must be explicitly declared
var f=a->a+" "; // can't know what type a is.
var f=String::replace; // method references aren't properly implied (weirdly, though)
在大多数情况下,您的程序将是单线程的,即它将仅运行一个线程。您可以return
在必须立即退出时通过从main方法中获取信息来利用这一事实。
static void main(String[]a){if(condition)return;}
将其与“适当地”终止程序进行比较:
static void main(String[]a){if(condition)System.exit(0);}
或指向null
:
static void main(String[]a){if(condition)throw null;}
或除以0:
static void main(String[]a){if(condition)int A=1/0;}
...
(varags)作为参数在某些情况下,使用Java varargs作为参数而不是松散的参数会更短。
例如:
// Example input/output: 5, 4, 3 -> 60000
int calculateVolumeInLiters(int width, int height, int depth){
return width * height * depth * 1000;
}
大多数人都会对此:
int c(int w,int h,int d){return w*h*d*1000;} // 44 bytes
但是可以为此打个额外的字节:
int c(int...a){return a[0]*a[1]*a[2]*1000;} // 43 bytes
请注意,在方法本身中,所有三个整数仅被访问一次。因为int
很短,所以只有在方法内部仅使用它们一次并且将其中三个或更多作为参数使用时,这才是有益的。
使用更长的参数通常会更有用。例如,这是我对此挑战的原始答案(计算输入字符串中输入字符的出现次数):
// Example input/output: tttggloyoi, t -> 3
int c(String a,char b){return a.replaceAll("[^"+b+"]","").length();} // 68 bytes
我被推荐去高尔夫球:
int c(String a,char b){return a.split(b+"").length-1;} // 54 bytes
但是我最终使用...
以下方法将其打高尔夫球:
int c(String...a){return a[0].split(a[1]).length-1;} // 52 bytes
注意:如果问题/挑战要求灵活输入,则...
可以将其缩短为[]
。假设问题/挑战专门要求三个String
输入,而不允许String
包含三个值的-array,则可以使用String...
代替String a,String b,String c
。
String[]
而不是使用varargs吗?(再节省1个字节)
package
可以跳过。