Thay thế một ký tự tại một chỉ mục cụ thể trong một chuỗi?


382

Tôi đang cố gắng thay thế một ký tự tại một chỉ mục cụ thể trong một chuỗi.

Những gì tôi đang làm là:

String myName = "domanokz";
myName.charAt(4) = 'x';

Điều này cho một lỗi. Có phương pháp nào để làm việc này không?


12
Tôi nhận ra điều này đã được trả lời cho đến chết, nhưng đáng chú ý là nó không bao giờ được phép gán kết quả của một cuộc gọi hàm trong java. Không có những thứ như tài liệu tham khảo của C (?) Và C ++.
Cách tiếp

1
@ValekHalfHeart trong VB, bạn sử dụng dấu ngoặc đơn để truy cập chỉ mục của một mảng, đó có thể là lý do khiến tôi bối rối khi tôi bắt đầu bằng Java: D
dpp

@ApproachingDarknessFish Tôi không chắc ý của bạn là gì "nó không bao giờ được phép gán kết quả của một cuộc gọi hàm trong java". Chắc chắn bạn có thể làm gì double r = Math.sin(3.14)? Làm thế nào nó liên quan đến câu hỏi này? Cảm ơn.
Flow2k

1
@ Flow2k Oh jeez, bình luận cũ vì vậy tôi không thể chỉnh sửa nhưng đó là một lỗi đánh máy, nên nói rằng "không bao giờ được phép gán cho kết quả của một lệnh gọi hàm trong Java". Tức là bạn có thể viết "foo = bar ();" nhưng không bao giờ "bar () = foo;".
Tiếp

Cảm ơn bạn đã làm rõ @ApproachingDarknessFish. Tôi nghĩ sẽ rất lạ khi gán một cái gì đó cho kết quả của một hàm - có ngôn ngữ nào thực sự cho phép điều này không? Tôi tự hỏi trường hợp sử dụng sẽ là gì.
Flow2k

Câu trả lời:


566

Chuỗi là bất biến trong Java. Bạn không thể thay đổi chúng.

Bạn cần tạo một chuỗi mới với ký tự được thay thế.

String myName = "domanokz";
String newName = myName.substring(0,4)+'x'+myName.substring(5);

Hoặc bạn có thể sử dụng StringBuilder:

StringBuilder myName = new StringBuilder("domanokz");
myName.setCharAt(4, 'x');

System.out.println(myName);

3
Ah, ý bạn là giống như replacephương thức sẽ không sửa đổi chuỗi mà sẽ chỉ trả về một chuỗi mới?
dpp

1
Điều đó khá phức tạp Mr.Petar. Đó có phải là cách tốt nhất để bạn làm điều đó? Ah, tôi đã nghe nói về StringBuilder trước đây, điều đó có tạo ra sự khác biệt nào không? Nó sẽ cho tôi một phương pháp dễ dàng hơn?
dpp

158

Biến Chuỗi thành char [], thay thế chữ cái theo chỉ mục, sau đó chuyển đổi mảng trở lại thành Chuỗi.

String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);

1
Yêu giải pháp này. Cuối cùng tôi đã thay đổi dòng thứ 3 thành myNameChars [index] = character.toCharArray () [0]; để đơn giản hóa. Giải pháp tốt đẹp.
Dale

2
nó trông tốt hơn nhiều so với cái xấu nhất khácmyName.substring(0,4)+'x'+myName.substring(5);
user924

Nó đơn giản hơn nhiều
Shiva Acharjee

19

Stringlà một lớp bất biến trong java. Bất kỳ phương thức nào có vẻ như sửa đổi nó luôn trả về một đối tượng chuỗi mới có sửa đổi.

Nếu bạn muốn thao tác một chuỗi, hãy xem xét StringBuilderhoặc StringBuffertrong trường hợp bạn yêu cầu an toàn luồng.


12

Tôi đồng ý với Petar Ivanov nhưng tốt nhất là chúng tôi thực hiện theo cách sau:

public String replace(String str, int index, char replace){     
    if(str==null){
        return str;
    }else if(index<0 || index>=str.length()){
        return str;
    }
    char[] chars = str.toCharArray();
    chars[index] = replace;
    return String.valueOf(chars);       
}

21
và điều gì làm cho giải pháp của bạn tốt hơn?
dpp

6

Như đã trả lời trước đây, các Stringtrường hợp là bất biến . StringBufferStringBuildercó thể thay đổi và phù hợp cho mục đích như vậy cho dù bạn có cần phải an toàn hay không.

Tuy nhiên, có một cách để sửa đổi Chuỗi nhưng tôi không bao giờ khuyến nghị vì nó không an toàn, không đáng tin cậy và nó có thể được coi là gian lận: bạn có thể sử dụng sự phản chiếu để sửa đổi charmảng bên trong mà đối tượng Chuỗi chứa. Reflection cho phép bạn truy cập các trường và phương thức thường được ẩn trong phạm vi hiện tại (phương thức riêng hoặc trường từ lớp khác ...).

public static void main(String[] args) {
    String text = "This is a test";
    try {
        //String.value is the array of char (char[])
        //that contains the text of the String
        Field valueField = String.class.getDeclaredField("value");
        //String.value is a private variable so it must be set as accessible 
        //to read and/or to modify its value
        valueField.setAccessible(true);
        //now we get the array the String instance is actually using
        char[] value = (char[])valueField.get(text);
        //The 13rd character is the "s" of the word "Test"
        value[12]='x';
        //We display the string which should be "This is a text"
        System.out.println(text);
    } catch (NoSuchFieldException | SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

4

Bạn có thể ghi đè một chuỗi, như sau:

String myName = "halftime";
myName = myName.substring(0,4)+'x'+myName.substring(5);  

Lưu ý rằng chuỗi myNamexảy ra trên cả hai dòng và trên cả hai mặt của dòng thứ hai.

Do đó, mặc dù các chuỗi có thể là bất biến về mặt kỹ thuật, trong thực tế, bạn có thể coi chúng là có thể chỉnh sửa bằng cách ghi đè chúng.


Tôi đã không đánh giá thấp câu trả lời của bạn nhưng tôi phải thừa nhận rằng tôi có vấn đề với thuật ngữ "ghi đè" (mặc dù tôi nghĩ rằng chúng tôi đồng ý về khái niệm đằng sau). Bản thân đối tượng vẫn không thay đổi. Bạn chỉ cần làm cho biến của bạn tham chiếu một đối tượng khác. Theo cách bạn thấy thú vị khi đề cập rằng bạn tạo ít nhất bốn trường hợp Chuỗi trong ví dụ của bạn.
C.Champagne

0

Điều đầu tiên tôi cần lưu ý là đó charAtlà một phương thức và gán giá trị cho nó bằng dấu bằng sẽ không làm gì cả. Nếu một chuỗi là bất biến, charAtphương thức, để thay đổi đối tượng chuỗi phải nhận được một đối số có chứa ký tự mới. Thật không may, chuỗi là bất biến. Để sửa đổi chuỗi, tôi cần sử dụng StringBuilder theo đề xuất của ông Petar Ivanov.


-7

cái này sẽ hoạt động

   String myName="domanokz";
   String p=myName.replace(myName.charAt(4),'x');
   System.out.println(p);

Đầu ra: domaxokz


1
mặc dù tôi cực kỳ ghét phương pháp được phép "chỉnh sửa" công việc của người khác trên trang web StackOverFlow này. hoàn toàn không công bằng: /
Diabolus Infernalis

2
Lỗi cú pháp. Và ngay cả khi được sửa, giả sử tôi muốn thay thế 'o' đầu tiên bằng 'x', 'o' thứ hai cũng sẽ được thay thế.
dpp

2
Điều này sẽ thay thế tất cả các nhân vật giống như charAt 4.
Shripad Bhat

1
Vấn đề: myName.replace(myName.charAt(5),'x')sẽ cung cấp cho bạn dxmanxkz, có lẽ không phải là những gì cần thiết.
Dawood ibn Kareem
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.