Tôi chỉ có thể làm điều này với String, ví dụ:
String str="";
for(int i=0;i<100;i++){
str=i+str;
}
Có cách nào để đạt được điều này với StringBuilder không? Cảm ơn.
Tôi chỉ có thể làm điều này với String, ví dụ:
String str="";
for(int i=0;i<100;i++){
str=i+str;
}
Có cách nào để đạt được điều này với StringBuilder không? Cảm ơn.
Câu trả lời:
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
sb.insert(0, Integer.toString(i));
}
Cảnh báo: Nó đánh bại mục đíchStringBuilder
, nhưng nó thực hiện những gì bạn yêu cầu.
Kỹ thuật tốt hơn (mặc dù vẫn không lý tưởng):
StringBuilder
.StringBuilder
khi bạn hoàn tất.Điều này sẽ biến một dung dịch O ( n ²) thành O ( n ).
Có thể tôi đang thiếu thứ gì đó nhưng bạn muốn kết thúc bằng một Chuỗi trông như thế này "999897969594...543210"
, đúng không?
StringBuilder sb = new StringBuilder();
for(int i=99;i>=0;i--){
sb.append(String.valueOf(i));
}
Là một giải pháp thay thế, bạn có thể sử dụng cấu trúc LIFO (như một ngăn xếp) để lưu trữ tất cả các chuỗi và khi bạn hoàn tất, chỉ cần lấy tất cả ra và đặt chúng vào StringBuilder. Nó tự nhiên đảo ngược thứ tự của các mục (chuỗi) được đặt trong đó.
Stack<String> textStack = new Stack<String>();
// push the strings to the stack
while(!isReadingTextDone()) {
String text = readText();
textStack.push(text);
}
// pop the strings and add to the text builder
String builder = new StringBuilder();
while (!textStack.empty()) {
builder.append(textStack.pop());
}
// get the final string
String finalText = builder.toString();
ArrayDeque
nên được sử dụng thay vì Stack
. "Một tập hợp các hoạt động ngăn xếp LIFO hoàn chỉnh và nhất quán hơn được cung cấp bởi giao diện {@link Deque} và các triển khai của nó. Giao diện này sẽ được ưu tiên sử dụng cho lớp này."
Chủ đề này khá cũ, nhưng bạn cũng có thể nghĩ về một giải pháp đệ quy chuyển StringBuilder để lấp đầy. Điều này cho phép ngăn chặn bất kỳ quá trình xử lý ngược nào, v.v. Chỉ cần thiết kế lặp lại của bạn với một đệ quy và cẩn thận quyết định điều kiện thoát.
public class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
doRecursive(sb, 100, 0);
System.out.println(sb.toString());
}
public static void doRecursive(StringBuilder sb, int limit, int index) {
if (index < limit) {
doRecursive(sb, limit, index + 1);
sb.append(Integer.toString(index));
}
}
}
Tôi đã có một yêu cầu tương tự khi tôi tình cờ đăng bài này. Tôi muốn một cách nhanh chóng để xây dựng một Chuỗi có thể phát triển từ cả hai phía. thêm chữ mới ở mặt trước cũng như mặt sau tùy ý. Tôi biết đây là một bài đăng cũ, nhưng nó đã thôi thúc tôi thử một vài cách tạo chuỗi và tôi nghĩ mình sẽ chia sẻ những phát hiện của mình. Tôi cũng đang sử dụng một số cấu trúc Java 8 trong này, có thể đã tối ưu hóa tốc độ trong trường hợp 4 và 5.
https://gist.github.com/SidWagz/e41e836dec65ff24f78afdf8669e6420
Gist ở trên có mã chi tiết mà bất kỳ ai cũng có thể chạy. Tôi đã thực hiện một số cách để phát triển dây trong này; 1) Nối vào StringBuilder, 2) Chèn vào trước StringBuilder như được hiển thị bởi @Mehrdad, 3) Chèn một phần từ trước cũng như cuối StringBuilder, 4) Sử dụng danh sách để nối từ cuối, 5) Sử dụng Deque vào nối từ phía trước.
// Case 2
StringBuilder build3 = new StringBuilder();
IntStream.range(0, MAX_STR)
.sequential()
.forEach(i -> {
if (i%2 == 0) build3.append(Integer.toString(i)); else build3.insert(0, Integer.toString(i));
});
String build3Out = build3.toString();
//Case 5
Deque<String> deque = new ArrayDeque<>();
IntStream.range(0, MAX_STR)
.sequential()
.forEach(i -> {
if (i%2 == 0) deque.addLast(Integer.toString(i)); else deque.addFirst(Integer.toString(i));
});
String dequeOut = deque.stream().collect(Collectors.joining(""));
Tôi sẽ tập trung vào các trường hợp chỉ nối thêm phía trước, tức là. trường hợp 2 và trường hợp 5. Việc thực thi StringBuilder nội bộ quyết định cách bộ đệm bên trong phát triển, điều này ngoài việc di chuyển tất cả bộ đệm từ trái sang phải trong trường hợp bổ sung phía trước sẽ hạn chế tốc độ. Mặc dù thời gian thực hiện khi chèn trực tiếp vào phía trước của StringBuilder tăng lên đến các giá trị thực sự cao, như được hiển thị bởi @Mehrdad, nếu nhu cầu là chỉ có các chuỗi có độ dài dưới 90k ký tự (vẫn còn nhiều), thì phần chèn phía trước sẽ xây dựng một Chuỗi trong cùng một thời gian vì nó sẽ cần để tạo một Chuỗi có cùng độ dài bằng cách thêm vào ở cuối. Những gì tôi đang nói là quả phạt thời gian thực sự phát huy tác dụng và rất lớn, nhưng chỉ khi bạn phải xây dựng một chuỗi thực sự lớn. Người ta có thể sử dụng một deque và nối các chuỗi ở cuối như trong ví dụ của tôi.
Trên thực tế, hiệu suất cho trường hợp 2 nhanh hơn nhiều so với trường hợp 1, mà tôi dường như không hiểu. Tôi giả định rằng sự tăng trưởng cho bộ đệm nội bộ trong StringBuilder sẽ giống nhau trong trường hợp phần phụ trước và phần phụ sau. Tôi thậm chí còn đặt heap tối thiểu thành một số lượng rất lớn để tránh sự chậm trễ trong tăng trưởng heap, nếu điều đó có thể đóng vai trò quan trọng. Có thể ai hiểu rõ hơn có thể comment bên dưới.
Difference Between String, StringBuilder And StringBuffer Classes
String
String is immutable ( once created can not be changed )object. The object created as a
String is stored in the Constant String Pool.
Every immutable object in Java is thread-safe, which implies String is also thread-safe. String
can not be used by two threads simultaneously.
String once assigned can not be changed.
StringBuffer
StringBuffer is mutable means one can change the value of the object. The object created
through StringBuffer is stored in the heap. StringBuffer has the same methods as the
StringBuilder , but each method in StringBuffer is synchronized that is StringBuffer is thread
safe .
Due to this, it does not allow two threads to simultaneously access the same method. Each
method can be accessed by one thread at a time.
But being thread-safe has disadvantages too as the performance of the StringBuffer hits due
to thread-safe property. Thus StringBuilder is faster than the StringBuffer when calling the
same methods of each class.
String Buffer can be converted to the string by using
toString() method.
StringBuffer demo1 = new StringBuffer("Hello") ;
// The above object stored in heap and its value can be changed.
/
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
StringBuilder is the same as the StringBuffer, that is it stores the object in heap and it can also
be modified. The main difference between the StringBuffer and StringBuilder is
that StringBuilder is also not thread-safe.
StringBuilder is fast as it is not thread-safe.
/
// The above object is stored in the heap and its value can be modified
/
// Above statement is right as it modifies the value which is allowed in the StringBuilder
Bạn có thể sử dụng phương pháp chèn với phần bù. như offset được đặt thành '0' có nghĩa là bạn đang thêm vào phía trước StringBuilder của mình.
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
sb.insert(0,i);
}
LƯU Ý : vì phương thức chèn chấp nhận tất cả các loại nguyên thủy, bạn có thể sử dụng cho int, long, char [], v.v.
Làm thế nào về:
StringBuilder builder = new StringBuilder();
for(int i=99;i>=0;i--){
builder.append(Integer.toString(i));
}
builder.toString();
HOẶC LÀ
StringBuilder builder = new StringBuilder();
for(int i=0;i<100;i++){
builder.insert(0, Integer.toString(i));
}
builder.toString();
Nhưng với điều này, bạn đang thực hiện phép toán O (N ^ 2) thay vì O (N).
Đoạn mã từ tài liệu java:
Chèn biểu diễn chuỗi của đối số Đối tượng vào chuỗi ký tự này. Hiệu ứng tổng thể chính xác như thể đối số thứ hai được chuyển đổi thành một chuỗi bằng phương thức
String.valueOf(Object)
và các ký tự của chuỗi đó sau đó được chèn vào chuỗi ký tự này tại độ lệch được chỉ định.
AbstractStringBuilder
tất cả các nội dung di chuyển qua chỉ mục của phần chèn để tìm chỗ cho những phần được chèn. Tuy nhiên, đó là một chi tiết thực hiện, không phải là một nguyên tắc.