English 中文(简体)
Java两条强令的最快途径是什么?
原标题:What s the fastest way to concatenate two Strings in Java?

Java两条强令的最快途径是什么?

i.e

String ccyPair = ccy1 + ccy2;

I m 采用cyPair 作为<代码>HashMap的关键,它呼吁在非常严格的循环中收回价值。

当我介绍时,这是瓶颈。

java.lang.StringBuilder.append(StringBuilder.java:119)  
java.lang.StringBuilder.(StringBuilder.java:93)
最佳回答

为什么这些惯例在基准中显示,这是因为汇编者如何在基准范围内执行你的“+”。

如果你真的需要加固的扼杀,那么你就应当让汇编者用“+”做魔".。 如果你们的所有需要都成为地图勘查的关键,那么,一个关键类别,即有适当的<条码>、平等<条/条码>和<条码>的“hashMap执行,可能是一个好的想法,因为它避免了复制步骤。

2023 edit: With Java 16 came records where the compiler does the hard work automatically under the covers. Just create a record with two string fields and you re done.

问题回答

理论之 Lo——某种做法的时间!

private final String s1 = new String("1234567890");
private final String s2 = new String("1234567890");

利用平原建造10 000 000 000个住宿点,安装了64个专用热点,在英特尔马座安装了16.022。

页: 1

@Test public void testConcatenation() {
    for (int i = 0; i < COUNT; i++) {
        String s3 = s1 + s2;
    }
}

With the following statements in the loops

String s3 = s1 + s2; 

1.33

String s3 = new StringBuilder(s1).append(s2).toString();

1.28

String s3 = new StringBuffer(s1).append(s2).toString();

1.92

String s3 = s1.concat(s2);

页: 1

String s3 = "1234567890" + "1234567890";

页: 1

因此,除非你有静态的插图,否则“星座”就是明显的赢家。

我认为,答案可能已经确定,但我是赞成守则的。

简短的答复,如果是完全的分类,就是:Sting.concat(......)

Output:

ITERATION_LIMIT1: 1
ITERATION_LIMIT2: 10000000
s1: STRING1-1111111111111111111111
s2: STRING2-2222222222222222222222

iteration: 1
                                          null:    1.7 nanos
                                 s1.concat(s2):  106.1 nanos
                                       s1 + s2:  251.7 nanos
   new StringBuilder(s1).append(s2).toString():  246.6 nanos
    new StringBuffer(s1).append(s2).toString():  404.7 nanos
                 String.format("%s%s", s1, s2): 3276.0 nanos

Tests complete

www.un.org/Depts/DGACM/index_spanish.htm 抽样法典:

package net.fosdal.scratch;

public class StringConcatenationPerformance {
    private static final int    ITERATION_LIMIT1    = 1;
    private static final int    ITERATION_LIMIT2    = 10000000;

    public static void main(String[] args) {
        String s1 = "STRING1-1111111111111111111111";
        String s2 = "STRING2-2222222222222222222222";
        String methodName;
        long startNanos, durationNanos;
        int iteration2;

        System.out.println("ITERATION_LIMIT1: " + ITERATION_LIMIT1);
        System.out.println("ITERATION_LIMIT2: " + ITERATION_LIMIT2);
        System.out.println("s1: " + s1);
        System.out.println("s2: " + s2);
        int iteration1 = 0;
        while (iteration1++ < ITERATION_LIMIT1) {
            System.out.println();
            System.out.println("iteration: " + iteration1);

            // method #0
            methodName = "null";
            iteration2 = 0;
            startNanos = System.nanoTime();
            while (iteration2++ < ITERATION_LIMIT2) {
                method0(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #1
            methodName = "s1.concat(s2)";
            iteration2 = 0;
            startNanos = System.nanoTime();
            while (iteration2++ < ITERATION_LIMIT2) {
                method1(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #2
            iteration2 = 0;
            startNanos = System.nanoTime();
            methodName = "s1 + s2";
            while (iteration2++ < ITERATION_LIMIT2) {
                method2(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #3
            iteration2 = 0;
            startNanos = System.nanoTime();
            methodName = "new StringBuilder(s1).append(s2).toString()";
            while (iteration2++ < ITERATION_LIMIT2) {
                method3(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #4
            iteration2 = 0;
            startNanos = System.nanoTime();
            methodName = "new StringBuffer(s1).append(s2).toString()";
            while (iteration2++ < ITERATION_LIMIT2) {
                method4(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #5
            iteration2 = 0;
            startNanos = System.nanoTime();
            methodName = "String.format("%s%s", s1, s2)";
            while (iteration2++ < ITERATION_LIMIT2) {
                method5(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));

        }
        System.out.println();
        System.out.println("Tests complete");

    }

    public static String method0(String s1, String s2) {
        return "";
    }

    public static String method1(String s1, String s2) {
        return s1.concat(s2);
    }

    public static String method2(String s1, String s2) {
        return s1 + s2;
    }

    public static String method3(String s1, String s2) {
        return new StringBuilder(s1).append(s2).toString();
    }

    public static String method4(String s1, String s2) {
        return new StringBuffer(s1).append(s2).toString();
    }

    public static String method5(String s1, String s2) {
        return String.format("%s%s", s1, s2);
    }

}

你们应当用在时间(例如UUID.randomUUID.toString())上产生的力量进行测试,而不是在编纂时(如“神秘”)。 我的结果

plus:     118 ns
concat:    52 ns
builder1: 102 ns
builder2:  66 ns
buffer1:  119 ns
buffer2:   87 ns

执行:

private static long COUNT = 10000000;

public static void main(String[] args) throws Exception {
    String s1 = UUID.randomUUID().toString();
    String s2 = UUID.randomUUID().toString();
    for(String methodName : new String[] {
            "none", "plus", "concat", "builder1", "builder2", "buffer1", "buffer2"
    }) {
        Method method = ConcatPerformanceTest.class.getMethod(methodName, String.class, String.class);
        long time = System.nanoTime();
        for(int i = 0; i < COUNT; i++) {
            method.invoke((Object) null, s1, s2);
        }
        System.out.println(methodName + ": " + (System.nanoTime() - time)/COUNT + " ns");
    }
}

public static String none(String s1, String s2) {
    return null;
}

public static String plus(String s1, String s2) {
    return s1 + s2;
}

public static String concat(String s1, String s2) {
    return s1.concat(s2);
}

public static String builder1(String s1, String s2) {
    return new StringBuilder(s1).append(s2).toString();
}

public static String builder2(String s1, String s2) {
    return new StringBuilder(s1.length() + s2.length()).append(s1).append(s2).toString();
}

public static String buffer1(String s1, String s2) {
    return new StringBuffer(s1).append(s2).toString();
}

public static String buffer2(String s1, String s2) {
    return new StringBuffer(s1.length() + s2.length()).append(s1).append(s2).toString();
}

标题中的问题:String.concat通常为编造两个String(但注)。 没有涉及[超大]中间缓冲或其他物体。 奇怪的是,<代码>+汇编成相对低效的代码,涉及<代码>StringBuilder。

然而,你问到其他问题。 努力绘制地图的关键是共同的“反异构体”。 这是一种黑板,容易发生错误。 你们是否相信所产生的关键是独特的? 在您的法典对一些尚不知的要求加以保留之后,这是否仍然具有独特性? 最好的办法是为钥匙建立一个不可改变的价值类别。 使用<代码>List 和通用读物类别是一种 s。

For me concat3 method as below is the fastest way after doing benchmark on my windows and remote linux machine:- Though i believe concat1 performance is JVM implementation and optimization dependent and may perform better in future version

    public class StringConcat {

    public static void main(String[] args) {
        int run = 100 * 100 * 1000;
        long startTime, total = 0;

        final String a = "a";
        final String b = "assdfsaf";
        final String c = "aasfasfsaf";
        final String d = "afafafdaa";
        final String e = "afdassadf";

        startTime = System.currentTimeMillis();
        concat1(run, a, b, c, d, e);
        total = System.currentTimeMillis() - startTime;
        System.out.println(total);

        startTime = System.currentTimeMillis();
        concat2(run, a, b, c, d, e);
        total = System.currentTimeMillis() - startTime;
        System.out.println(total);

        startTime = System.currentTimeMillis();
        concat3(run, a, b, c, d, e);
        total = System.currentTimeMillis() - startTime;
        System.out.println(total);
    }

    private static void concat3(int run, String a, String b, String c, String d, String e) {
        for (int i = 0; i < run; i++) {
            String str = new StringBuilder(a.length() + b.length() + c.length() + d.length() + e.length()).append(a)
                    .append(b).append(c).append(d).append(e).toString();
        }
    }

    private static void concat2(int run, String a, String b, String c, String d, String e) {
        for (int i = 0; i < run; i++) {
            String str = new StringBuilder(a).append(b).append(c).append(d).append(e).toString();
        }
    }

    private static void concat1(int run, String a, String b, String c, String d, String e) {
        for (int i = 0; i < run; i++) {
            String str = a + b + c + d + e;
        }
    }
}

我建议尝试苏比约恩·拉夫恩·安德斯建议。

如果你需要根据两部分的长短而压缩的强权,则可能更能创造所需规模的强硬度,以避免重新分配。 违约建筑师保留了目前执行中的16个特征,至少是我的机器。 因此,如果所加固的强权比最初的缓冲规模长,斯特林德必须重新定位。

引证并告诉我们贵方说:

StringBuilder ccyPair = new StringBuilder(ccy1.length()+ccy2.length());
ccyPair.append(ccy1); 
ccyPair.append(ccy2); 

Perhaps instead of concatenation, you should create a Pair class?

public class Pair<T1, T2> {
    private T1 first;
    private T2 second;

    public static <U1,U2> Pair<U1,U2> create(U1 first, U2 second) {
        return new Pair<U1,U2>(U1,U2);
    }

    public Pair( ) {}

    public Pair( T1 first, T2 second ) {
        this.first = first;
        this.second = second;
    }

    public T1 getFirst( ) {
        return first;
    }

    public void setFirst( T1 first ) {
        this.first = first;
    }

    public T2 getSecond( ) {
        return second;
    }

    public void setSecond( T2 second ) {
        this.second = second;
    }

    @Override
    public String toString( ) {
        return "Pair [first=" + first + ", second=" + second + "]";
    }

    @Override
    public int hashCode( ) {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((first == null)?0:first.hashCode());
        result = prime * result + ((second == null)?0:second.hashCode());
        return result;
    }

    @Override
    public boolean equals( Object obj ) {
        if ( this == obj )
            return true;
        if ( obj == null )
            return false;
        if ( getClass() != obj.getClass() )
            return false;
        Pair<?, ?> other = (Pair<?, ?>) obj;
        if ( first == null ) {
            if ( other.first != null )
                return false;
        }
        else if ( !first.equals(other.first) )
            return false;
        if ( second == null ) {
            if ( other.second != null )
                return false;
        }
        else if ( !second.equals(other.second) )
            return false;
        return true;
    }

}

并将之作为你在哈希姆博普的钥匙

而不是HashMap<String, Whatever>

在你紧凑的路程中,不使用<条码>。

根据Java specification(href=”http://web.archive.org/web/1205170952/http://java.sun.com:80/docs/books/jls/first_edition/html/15.doc.html#406" rel=sttht=sthatresection

To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression

因此,基本上使用<代码>+营运人或-StringBuilder.append对变量而言基本相同。


其他事情,我知道,在你提出的问题中,你提到只增加两处力量,但铭记增加三处或更多力量将产生不同的结果:

我使用了略为修改的@Duncan McGregor实例。 我有5种方法,使用混凝土和5种方法,利用StingBuilder ,压缩2至6条str:

// Initialization
    private final String s1 = new String("1234567890");
    private final String s2 = new String("1234567890");
    private final String s3 = new String("1234567890");
    private final String s4 = new String("1234567890");
    private final String s5 = new String("1234567890");
    private final String s6 = new String("1234567890");

// testing the concat
    public void testConcatenation2stringsConcat(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = s1.concat(s2);
        }
    }
    public void testConcatenation3stringsConcat(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = s1.concat(s2).concat(s3);
        }
    }
    public void testConcatenation4stringsConcat(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = s1.concat(s2).concat(s3).concat(s4);
        }
    }
    public void testConcatenation5stringsConcat(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = s1.concat(s2).concat(s3).concat(s4).concat(s5);
        }
    }
    public void testConcatenation6stringsConcat(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = s1.concat(s2).concat(s3).concat(s4).concat(s5).concat(s6);
        }
    }

//testing the StringBuilder
    public void testConcatenation2stringsSB(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = new StringBuilder(s1).append(s2).toString();
        }
    }
    public void testConcatenation3stringsSB(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = new StringBuilder(s1).append(s2).append(s3).toString();
        }
    }
    public void testConcatenation4stringsSB(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = new StringBuilder(s1).append(s2).append(s3).append(s4).toString();
        }
    }
    public void testConcatenation5stringsSB(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = new StringBuilder(s1).append(s2).append(s3).append(s4).append(s5).toString();
        }
    }
    public void testConcatenation6stringsSB(int count) {
        for (int i = 0; i < count; i++) {
            String s100 = new StringBuilder(s1).append(s2).append(s3).append(s4).append(s5).append(s6).toString();
        }
    }

我取得了这些成果(第二点):

testConcatenation2stringsConcat : 0.018 |||||||||||||||| testConcatenation2stringsSB : 0.2 testConcatenation3stringsConcat : 0.35 ||||||||||||||||||| testConcatenation3stringsSB : 0.25 testConcatenation4stringsConcat : 0.5 |||||||||||||||||||||| testConcatenation4stringsSB : 0.3 testConcatenation5stringsConcat : 0.67 ||||||||||||||||||| testConcatenation5stringsSB : 0.38 testConcatenation5stringsConcat : 0.9 |||||||||||||||||||||| testConcatenation5stringsSB : 0.43

  • You can see that concat is faster than StringBuilder only when concatenating only 2 Strings
  • See that when adding more and more Strings, the StringBuilder resulting time is increasing more slowly that using the concat
  • Note that the difference will be more significant when the strings are very long

Interestingly,StringJoiner <>m>sn t referred here...

通常,必须在示意图之间插入一个分离器,例如”、“>。 该代码比使用<代码>StringBuilder和类似快速读。

StringJoiner joiner = new StringJoiner( ", " );
joiner.add( ccy1 ).add( ccy2 );

或许,你可以单独计算两条插头的 has子,然后把它们结合起来,或许与单列的散射功能相结合。

类似:

int h1 = ccy1.hashCode(), h2 = ccy2.hashCode(), h = h1 ^ h2;

这很可能是更快的,因为加固的扼杀仅仅是为了对 con酸 has进行消化似乎是浪费的。

请注意,上述两条斜线与双向-XOR(^的操作者”)合并,后者经常运作,但你可能希望进一步调查。

Ok, so what is your question? Nothing to do: if you have to concatenate strings just do it. It is fine that you profiled your code. Now you can see the fact that string concatenation operator + automatically uses StringBuilder s append() method, so using

StringBuilder ccyPair = new StringBuilder(ccy1)
ccyPair.append(ccy2);

不能给你带来严重的好处。

优化你的法典的唯一认真方法可能是改变你的意图,完全排除这种调子。 但是,只有当你真的需要时,也就是在万国邮联相当一部分时间时,才会这样做。

@Duncan McGregors 回答给出了一个特定例子(输入方位)和一台证书版本的基准数字。 在这种情况下,它像<代码>String.concat()”一样,是一个重要因素的赢家。 这一结果可能或不可能概括。

其他: 我感到惊讶! d 我已经认为,汇编者作者本会选择使用强硬。 如果情况可能较快,就会发生混乱。 解释载于,该bug报告......,并植根于Sting concatenation营运人的定义。

(如果+>>的硬型操作体是null,则联合体称“Stingnull”在其位置上使用。 如果编码生成<代码> + s2,作为<编码>s.concat(s2)和ss2 页: 1 <代码>s = = 无的情况是指<编码>的备选案文。 并没有解决民族解放军问题。


然而,@unwind的回答给我一个想法,那就是,要找到一种替代解决办法,避免需要加以分类。

如果刚刚将<代码>ccy1和ccy 2合并为两个钥匙,那么,或许可以通过确定一个特别的散列表格类别来提高绩效,该类别将有两个关键而不是一个。 它有以下行动:

    public Object get(String key1, String key2) ...

    public void put(String key1, String key2, Object value) ...

效果如<代码>Map<Pair<String, String>, Object>(见@KitsuneYMG swer),但不必创建<代码>Pair<String, String>每次你想要填写<编码>。 倒数为:

  • you have to implement a new hash table class from the ground up, and
  • the new class won t conform to the Map interface.

通常,我不建议这样做。 然而,如果扼杀的分类和地图勘测确实是一个关键的瓶颈,那么一个多基的定制表可能会使你大大加快速度。

这里是全面执行线性图瓦/双钥匙,单一价值。 它应战胜 j。 HashMap nicely也是如此。

警告说,它从头几个小时就发出警告,因此可能含有ug。 敬请.。

The solution must beat any wrapper, concat one at any time. The no allocation on get/put also makes it quick general purpose map.

希望能解决这个问题。 (《法典》是带的,有些简单的测试是不需要的)


package bestsss.util;


@SuppressWarnings("unchecked")
public class DoubleKeyMap<K1, K2, V> {
    private static final int MAX_CAPACITY =  1<<29; 

    private static final Object TOMBSTONE = new String("TOMBSTONE");

    Object[] kvs; 
    int[] hashes;
    int count = 0;

    final int rehashOnProbes;   

    public DoubleKeyMap(){
        this(8, 5);
    }

    public DoubleKeyMap(int capacity, int rehashOnProbes){
        capacity = nextCapacity(Math.max(2, capacity-1));
        if (rehashOnProbes>capacity){
            throw new IllegalArgumentException("rehashOnProbes too high");
        }
        hashes = new int[capacity];
        kvs = new Object[kvsIndex(capacity)];       
        count = 0;
        this.rehashOnProbes = rehashOnProbes;
    }

    private static int nextCapacity(int c) {
        int n = Integer.highestOneBit(c)<<1;
        if (n<0 || n>MAX_CAPACITY){
            throw new Error("map too large");
        }
        return n;
    }

    //alternatively this method can become non-static, protected and overriden, the perfoamnce can drop a little
    //but if better spread of the lowest bit is possible, all good and proper
    private static<K1, K2> int hash(K1 key1, K2 key2){
        //spread more, if need be
        int h1 = key1.hashCode();
        int h2 = key2.hashCode();
        return h1+ (h2<<4) + h2; //h1+h2*17
    }

    private static int kvsIndex(int baseIdx){
        int idx = baseIdx;  
        idx+=idx<<1;//idx*3
        return idx;
    }

    private int baseIdx(int hash){
        return hash & (hashes.length-1);
    }

    public V get(K1 key1, K2 key2){
        final int hash = hash(key1, key2);


        final int[] hashes = this.hashes;
        final Object[] kvs = this.kvs;
        final int mask = hashes.length-1;

        for(int base = baseIdx(hash);;base=(base+1)&mask){
            int k = kvsIndex(base);
            K1 k1 = (K1) kvs[k];
            if (k1==null)
                return null;//null met; no such value

            Object value;
            if (hashes[base]!=hash || TOMBSTONE==(value=kvs[k+2]))
                continue;//next

            K2 k2 = (K2) kvs[k+1];
            if ( (key1==k1 || key1.equals(k1)) && (key2==k2 || key2.equals(k2)) ){
                return (V) value;
            }
        }
    }
    public boolean contains(K1 key1, K2 key2){
        return get(key1, key2)!=null;
    }

    public boolean containsValue(final V value){
        final Object[] kvs = this.kvs;
        if (value==null)
            return false;

        for(int i=0;i<kvs.length;i+=3){
            Object v = kvs[2];
            if (v==null || v==TOMBSTONE)
                continue;
            if (value==v || value.equals(v))
                return true;
        }
        return false;
    }

    public V put(K1 key1, K2 key2, V value){
        int hash = hash(key1, key2);
        return doPut(key1, key2, value, hash);
    }
    public V remove(K1 key1, K2 key2){
        int hash = hash(key1, key2);
        return doPut(key1, key2, null, hash);   
    }

    //note, instead of remove a TOMBSTONE is used to mark the deletion
    //this may leak keys but deletion doesn t need to shift the array like in Knuth 6.4
    protected V doPut(final K1 key1, final K2 key2, Object value, final int hash){
        //null value -> remove
        int probes = 0;
        final int[] hashes = this.hashes;
        final Object[] kvs = this.kvs;
        final int mask = hashes.length-1;

        //conservative resize: when too many probes and the count is greater than the half of the capacity
        for(int base = baseIdx(hash);probes<rehashOnProbes || count<(mask>>1);base=(base+1)&mask, probes++){
            final int k = kvsIndex(base);
            K1 k1 = (K1) kvs[k];
            K2 k2;
            //find a gap, or resize
            Object  old  = kvs[k+2];
            final boolean emptySlot = k1==null || (value!=null && old==TOMBSTONE); 
            if (emptySlot || (
                    hashes[base] == hash &&
                    (k1==key1  || k1.equals(key1)) &&
                    ((k2=(K2) kvs[k+1])==key2 || k2.equals(key2))) 
            ){

                if (value==null){//remove()
                    if (emptySlot)
                        return null;//not found, and no value ->nothing to do

                    value = TOMBSTONE;
                    count-=2;//offset the ++later
                }

                if (emptySlot){//new entry, update keys
                    hashes[base] = hash;                
                    kvs[k] = key1;
                    kvs[k+1] = key2;
                }//else -> keys and hash are equal


                if (old==TOMBSTONE) 
                    old=null;

                kvs[k+2] = value;
                count++;

                return (V) old;
            }
        }
        resize();
        return doPut(key1, key2, value, hash);//hack w/ recursion, after the resize
    }

    //optimized version during resize, doesn t check equals which is the slowest part   
    protected void doPutForResize(K1 key1, K2 key2, V value, final int hash){
        final int[] hashes = this.hashes;
        final Object[] kvs = this.kvs;
        final int mask = hashes.length-1;

        //find the 1st gap and insert there
        for(int base = baseIdx(hash);;base=(base+1)&mask){//it s ensured, no equal keys exist, so skip equals part
            final int k = kvsIndex(base);
            K1 k1 = (K1) kvs[k];
            if (k1!=null) 
                continue;

            hashes[base] = hash;                
            kvs[k] = key1;
            kvs[k+1] = key2;
            kvs[k+2] = value;
            return;
        }
    }

    //resizes the map by doubling the capacity, 
    //the method uses altervative varian of put that doesn t check equality, or probes; just inserts at a gap
    protected void resize(){        
        final int[] hashes = this.hashes;
        final Object[] kvs = this.kvs;
        final int capacity = nextCapacity(hashes.length);

        this.hashes = new int[capacity];
        this.kvs = new Object[kvsIndex(capacity)];

        for (int i=0;i<hashes.length; i++){
            int k = kvsIndex(i);
            K1 key1 = (K1) kvs[k];
            Object value = kvs[k+2];
            if (key1!=null && TOMBSTONE!=value){
                K2 key2 = (K2) kvs[k+1];
                doPutForResize(key1, key2, (V) value, hashes[i]);
            }
        }   
    }

    public static void main(String[] args) {
        DoubleKeyMap<String, String, Integer> map = new DoubleKeyMap<String, String, Integer>(4,2);
        map.put("eur/usd", "usd/jpy", 1);
        map.put("eur/usd", "usd/jpy", 2);

        map.put("eur/jpy", "usd/jpy", 3);

        System.out.println(map.get("eur/jpy", "usd/jpy"));
        System.out.println(map.get("eur/usd", "usd/jpy"));
        System.out.println("======");

        map.remove("eur/usd", "usd/jpy");
        System.out.println(map.get("eur/jpy", "usd/jpy"));
        System.out.println(map.get("eur/usd", "usd/jpy"));
        System.out.println("======");
        testResize();
    }
    static void testResize(){
        DoubleKeyMap<String, Integer, Integer> map = new DoubleKeyMap<String, Integer, Integer>(18, 17);
        long s = 0;
        String pref="xxx";

        for (int i=0;i<14000;i++){
            map.put(pref+i, i, i);

            if ((i&1)==1)
                map.remove(pref+i, i);
            else
                s+=i;
        }
        System.out.println("sum: "+s);
        long sum = 0;

        for (int i=0;i<14000;i++){
            Integer n = map.get(pref+i, i);
            if (n!=null && n!=i){
                throw new AssertionError(); 
            }
            if (n!=null){
                System.out.println(n);
                sum+=n;
            }
        }
        System.out.println("1st sum: "+s);
        System.out.println("2nd sum: "+sum);


    }
}
StringBuffer ccyPair =  new StringBuffer();      
ccyPair.append("ccy1").append("ccy2"); 

您是否尝试使用“Sting Buffer”,然后使用“简介”来审查瓶颈之处。 把它当作一个尝试,看什么发生。

铭记,如果你正在策划数以百万计的扼杀,那么就会扼杀。 混凝土极有可能产生数百万新的扼杀物。 这将增加使用CPU。

我决定尝试制定基准,这里是我的结果。 我猜测采用“+”计算法是最容易和最快(或几乎是最快的)方式。

JMH version: 1.19
VM version: JDK 1.8.0_211, VM 25.211-b12
VM options: -Xms2G -Xmx2G
Warmup: 10 iterations, 1 s each
Measurement: 30 iterations, 1 s each
Timeout: 10 min per iteration
Threads: 1 thread, will synchronize iterations
Benchmark mode: Average time, time/op
Parameters: (N = 1000000)

Benchmark          (N)  Mode  Cnt  Score     Error  Units
concat         1000000  avgt   30  24.839  ± 0.211  ms/op
plus           1000000  avgt   30  15.072  ± 0.155  ms/op
stringBuffer   1000000  avgt   30  14.835  ± 0.118  ms/op
stringBuilder  1000000  avgt   30  14.775  ± 0.205  ms/op

这里是法典:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(value = 2, jvmArgs = {"-Xms2G", "-Xmx2G"})
@Warmup(iterations = 10)
@Measurement(iterations = 30)
public class BenchmarkString {

    @Param({"1000000"})
    private int N;
    private final String s1 = new String("1234567890124567890");
    private final String s2 = new String("1234567890124567890");

    public static void main(String[] args) throws RunnerException {

        Options opt = new OptionsBuilder()
                .include(BenchmarkString.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }

    @Benchmark
    public void plus() {
        for (int i = 0; i < N; i++) {
            String s = s1 + s2;
        }
    }

    @Benchmark
    public void stringBuilder() {
        for (int i = 0; i < N; i++) {
            String s = new StringBuilder(s1).append(s2).toString();
        }
    }

    @Benchmark
    public void stringBuffer() {
        for (int i = 0; i < N; i++) {
            String s = new StringBuffer(s1).append(s2).toString();
        }
    }

    @Benchmark
    public void concat() {
        for (int i = 0; i < N; i++) {
            String s = s1.concat(s2);
        }
    }
}




相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...