2010-05-25 15 views
6

tôi có mã này để concate một số phần tử mảng:Có phương pháp nhanh hơn sau đó StringBuilder cho chuỗi nối tối đa 9-10 bước không?

StringBuilder sb = new StringBuilder(); 
private RatedMessage joinMessage(int step, boolean isresult) { 
     sb.delete(0, sb.length()); 
     RatedMessage rm; 
     for (int i = 0; i <= step; i++) { 
      if (mStack[i] == null) 
       continue; 
      rm = mStack[i].getCurrentMsg();// msg is built upfront, this just returns, it's a getter method call 
      if (rm == null || rm.msg.length() == 0) 
       continue; 
      if (sb.length() != 0) { 
       sb.append(", "); 
      } 
      sb.append(rm.msg); 
     } 
     rm.msg=sb.toString(); 
     return rm; 
    } 

quan trọng mảng nắm giữ tối đa 10 mặt hàng, do đó, nó không phải là khá nhiều.

Kết xuất theo dõi của tôi cho tôi biết phương pháp này được gọi là 18864 lần, 16% thời gian chạy đã được sử dụng trong phương pháp này. Tôi có thể tối ưu hóa nhiều hơn không?

+0

phương pháp của bạn nói nó có một kiểu trả về của RatedMessage nhưng nó xuất hiện trở lại một chuỗi. Có chuyện gì thế? Ngoài ra, các đối tượng rm.msg này lớn đến mức nào, chúng có phải là các chuỗi hoặc có một hàm toString ngầm được gọi lên chúng không? – luke

+0

Xin lỗi, tôi đã giảm mã xuống phần thiết yếu. Có một tỷ lệ, số phao cho mỗi msg. rm là viết tắt của RatingMessage. – Pentium10

+1

@ Pentium10, tôi nghĩ bạn cắt quá nhiều. Bạn có một điểm nóng và bạn về cơ bản giả định rằng một số điều không phải là vấn đề và sau đó hỏi về phần còn lại. Nếu bạn có mã làm việc mà bạn đã hiển thị vẫn còn chậm nhưng đơn giản hơn (nếu bị hỏng theo nghĩa là nó trả lời sai), điều đó thật tuyệt, nhưng đừng cắt ra quá nhiều và mong đợi để có được câu trả lời có ý nghĩa ở đây. – Yishai

Trả lời

3

một số ý tưởng:

1) Bạn có khởi tạo StringBuilder với công suất tối đa ước tính không? Điều này có thể tiết kiệm thời gian dành cho việc sao chép lại mảng nội bộ & sao chép.

2) Có thể bạn có thể gắn thêm trailing dấu phẩy trong vòng lặp và tránh điều kiện cho độ dài chuỗi bên trong vòng lặp. Thay vào đó, hãy thêm một điều kiện ở cuối phương thức và xóa dấu phẩy sau nếu cần.

5

Trước hết, tôi sẽ không sử dụng lại StringBuilder và luôn tạo phiên bản mới. Điều đó sẽ chắc chắn nhanh hơn, bởi vì nó sẽ cho phép GC sử dụng khu vực heap thế hệ trẻ.

Một mẹo nhỏ cho phép loại bỏ ít nhất một câu lệnh if là phải viết lại mã của bạn như thế này:

String separator = ""; 
    for (int i = 0; i <= step; i++) { 
     ... 
     sb.append(separator); 
     sb.append(rm.msg); 
     separator = ", "; 
    } 
+0

Liệu nhiệm vụ bổ sung có hiệu suất tốt hơn-khôn ngoan hơn câu lệnh if? Hoặc là nó được tối ưu hóa một cách kỳ diệu bởi trình biên dịch? –

+0

Một cách khác để loại bỏ khối if đó mà không thêm phép gán là di chuyển điều kiện thoát ra khỏi đầu trang for-loop và vào chính vòng lặp: 'if (i <= step) break; sb.append (separator); ' –

0

Nếu chức năng của bạn có nghĩa vụ phải nối các phần tử mảng, tại sao bạn đi qua trong tất cả các giá trị điên và các tham số không sử dụng?

private string joinMessage(string[] myArray) 
{ 
    StringBuilder sbr = new StringBuilder(); 
    for(int i = 0; i < myArray.Length; i++) 
    { 
    if(!string.IsNullOrEmpty(myArray[i]) 
    { 
     sbr.Append(myArray[i]); 
     sbr.Append(",") 
    } 
    } 
    return sbr.ToString(); 
} 
+0

Tôi có một số thứ nhỏ khác trong đó, xem bình luận của tôi về câu hỏi chính. – Pentium10

+0

Tôi không tranh luận rằng bạn không cần phải trả lại một RatingMessage hoặc làm bất cứ điều gì như thế, tôi nói rằng nếu điểm của phương thức là "Lấy một chuỗi các chuỗi và trả về một chuỗi đã xóa dấu phẩy của tất cả các phần tử nối liền ", bất cứ thứ gì ngoài đó là vô giá trị (vì mục đích của cuộc thảo luận này) –

1

Bạn có thể thực hiện thay đổi như sau (chỉ hiển thị sự khác biệt):

String separator = ""; 
    for (int i = 0; i <= step; i++) { 
    // ... 
     sb.append(separator).append(rm.msg); 
     separator = ", "; 
    } 

Nó giúp loại bỏ nếu thêm nếu 9 lần với chi phí của việc thêm một chuỗi rỗng một lần. Bạn nên đo lường nếu nó giúp ở tất cả với dữ liệu bạn đang sử dụng trước khi bạn quyết định giữ sự thay đổi này :-)

0

Thực hiện một bước qua từng phần tử trong ngăn xếp trước, tính tổng của tất cả các độ dài chuỗi .

Sau đó, bạn có thể sử dụng

sb.ensureCapacity(totalEndLength); 

Chuỗi xây dựng hoạt động giống như một array list, vì vậy bạn có thể xây dựng lại mảng mà với hầu hết gắn thêm của bạn.

0

Một chút tối ưu hóa nhỏ ... lấy dấu kiểm tra cho dấu phẩy bên ngoài vòng lặp.

private RatedMessage joinMessage(int step, boolean isresult) { 
    sb.delete(0, sb.length()); 
    for (int i = 0; i <= step; i++) { 
     if (mStack[i] == null) 
      continue; 
     rm = mStack[i].getCurrentMsg(); 
     if (rm == null || rm.msg.length() == 0) 
      continue; 
     sb.append(rm.msg).append(", "); 
    } 
    if (sb.length() > 2) { 
     sb.delete(sb.length() - 2, 2); 
    } 
    return sb.toString(); 
} 

gợi ý khác sẽ là:

  • Hãy chắc chắn rằng khi StringBuilder được xây dựng bạn thiết lập chiều dài ban đầu của nó đến một giá trị khá
  • Tôi không chắc chắn về bối cảnh của phần còn lại của mã, nhưng có thể bạn có thể đảm bảo rằng mStack [i] sẽ không rỗng, và mStack [i] .getCurrentMessage() không rỗng hoặc rỗng - điều này sẽ cho phép bạn lấy nhiều hơn nếu các câu lệnh nằm ngoài vòng lặp.
0

Có một bản sao riêng của mảng mStack với chuỗi đại diện, theo mặc định khởi tạo với chuỗi rỗng, vì vậy vòng lặp của bạn sẽ là:

String [] mStackCopy = new String[]{"","","","","","","","","","",}; 
// or mstackCopy = new String[mStack.length]; 
// for(int i = 0 ; i < mStackCopy.lenght ; i++) { mStack[i] = "" } 

Ngoài ra, tạo StringBuilder với đủ công suất:

StringBuilder sb = new StringBuilder(10000);// 10k chars or whatever makes sense. 

Vì vậy, khi bạn cần để tạo ra các thông điệp mà bạn sẽ chỉ đơn giản là:

for (int i = 0; i <= step; i++) { 
    sb.append(mStackCopy[i]); 
} 

Và trống phần sẽ không gây ra một vấn đề, vì họ là trống đã:

Bạn thậm chí có thể cứng mã nó:

sb.append(mStackCopy[0]); 
sb.append(mStackCopy[1]); 
sb.append(mStackCopy[2]); 
sb.append(mStackCopy[3]); 
sb.append(mStackCopy[4]); 
sb.append(mStackCopy[5]); 
sb.append(mStackCopy[6]); 
sb.append(mStackCopy[7]); 
sb.append(mStackCopy[8]); 
sb.append(mStackCopy[9]); 

Nhưng điều này sẽ gây ra đau đớn hơn cứu trợ trong tương lai, đảm bảo.

Khi bạn thêm một cái gì đó để mStack của bạn:

MStack item = new MStack(); 
item.setCurrentMessage("Some message"); 

.... 

Chỉ cần tạo một bản sao của thông điệp và gắn "" rồi.

addToMStack(int position, MStackItem item) { 
    mStack[position] = item; 
    mStackCopy[position] = item.getCurrentMessage() + ", "; 
} 

Và tùy thuộc vào sự xuất hiện của null (nếu thấp), bạn có thể bắt chúng

addToMStack(int position, MStackItem item) { 
    if(item == null) { return; } 
    mStack[position] = item; 
    try { 
     mStackCopy[position] = item.getCurrentMessage() + ", "; 
    } catch(NullPointerException npe){} 
} 

Đó là khủng khiếp

Hoặc xác nhận điều đó:

addToMStack(int position, MStackItem item) { 
    if(item == null) { return; } 
    mStack[position] = item; 
    mStackCopy[position] = item.getCurrentMessage() + ", "; 
} 

Tôi khá chắc chắn phương pháp của bạn đang làm điều gì đó khác mà bạn không cho chúng tôi thấy. Có lẽ lý do là ở đó.

Ngoài ra, 16% không phải là xấu, nếu 100% là 1 giây.

+0

Vì tôi đang chạy trên thiết bị di động chậm hơn nhiều. Ở trên nói với 18864 bước mất 8-10 giây. – Pentium10

0

Nếu mStack của bạn là Bộ sưu tập thay vì mảng, bạn chỉ có thể thực hiện mStack.toString(), sẽ in chuỗi có thể đọc được của mảng. Điều đó có thể dễ dàng hơn là viết của riêng bạn.

0

Thời gian chạy 16% theo phương pháp này bao gồm hoặc không bao gồm được gọi là phương pháp? Cuộc gọi getCurrentMsg() có thể là một vấn đề ẩn, nếu nó tạo ra nhiều đối tượng.

Bên cạnh đó, tôi đề nghị để đưa tất cả các Strings cần thiết ra khỏi ngăn xếp của bạn và sau đó gọi

StringUtils.join(myStrings, ", ")

sử dụng Apache commons library. Hãy thử dựa vào mã thử nghiệm cho những thứ cấp thấp như vậy thay vì tự tối ưu hóa nó mỗi ngày. Cuối cùng sẽ cho bạn kết quả tối ưu hóa tốt hơn bởi vì bạn sẽ có thể tập trung vào bức tranh lớn (tức là thiết kế tổng thể của phần mềm của bạn).

+0

tát bản thân mình vì không nhận thấy nhận xét bên cạnh cuộc gọi đó. Tuy nhiên, đề xuất StringUtils vẫn còn. :) – Bananeweizen

+0

nó bao gồm, độc quyền là 12% một cái gì đó – Pentium10

0

Đôi khi không có gì khác để tối ưu hóa. Tôi nghĩ đây là một trong những trường hợp như vậy.Bạn có thể cố gắng cắt bỏ một hoặc hai hướng dẫn có thể, nhưng bạn sẽ không làm cho nó nhanh hơn về nguyên tắc.

Tôi nghĩ điều duy nhất còn lại để tối ưu hóa là xem xét lý do tại sao bạn gọi số này là 18864 lần và có thể tránh được một số cuộc gọi đó hay không. Có lẽ một số là không cần thiết, hoặc có lẽ bạn có thể cache kết quả trong một số trường hợp.

+0

nó là một phần của một quá trình tạo máy nhà nước, khi một trạng thái đạt trạng thái Dừng, nó tạo ra một kết quả. Nó đã giảm một số cách từ 2M giá trị chỉ 18k lần được gọi. – Pentium10

0

Sử dụng StringBuilder + StringUtils từ Apache Commons Lang. Looping thông qua một String với một dấu phân cách và chomping là những gì StringUtils là tất cả về!

private RatedMessage joinMessage(int step, boolean isresult) { 
     StringBuilder builder = new StringBuilder(); 
     for (int i = 0; i <= step; i++) { 
      WhateverTypeIsFromMStackVariable stackVariable = mStack[i]; 
      String message = getMessage(stackVariable); 
      if(StringUtils.isNotEmpty(message)) { 
       builder.append(message).append(", "); 
      } 
     } 
     RatedMessage rm = new RatedMessage(); 
     rm.msg = StringUtils.chomp(builder.toString(), ", "); 
     return rm; 
    } 

private static String getMessage(WhateverTypeIsFromMStackVariable stackVariable) { 
    if(stackVariable != null) { 
     RatedMessage message = stackVariable.getCurrentMsg(); 
     if(message != null) { 
      return message.msg; 
     } 
    } 
    return null; 
} 

Apache Commons Lang là ở đây: http://commons.apache.org/lang/

Các vấn đề liên quan