🍓 简介:java系列技术分享(👉持续更新中…🔥)
🍓 初衷:一起学习、一起进步、坚持不懈
🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏
🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝
文章目录
问题描述
需要将List集合中的每个元素按规则截取一部分然后再赋值给当前元素,但是结果没有发生改变
什么原因呢,那么我用下面简单的例子来进行解释。
一、 将List集合中的每个字符串更改为其他值(有问题)
public class TestDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for (String str : list) {
str ="修改";
}
System.out.println(list);
}
当前打印结果是什么呢?
和预期结果不一致
[a, b, c, d]
当然我想你肯定是知道的,但是为什么会这样呢?为什么结果没有发生改变呢?
这里尝试通过对 list 中的每个字符串进行循环迭代并将其赋值为 “修改”,
但实际上这并不会改变 list 中的元素。原因是在 Java 中, for 循环中的循环变量 str 是一个临时变量,它只是一个指向列表中元素的引用,修改 str 并不会影响到列表中的元素。
二、 将List集合中的每个对象实例更改为其他实例(有问题)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student{
private String name;
private int age;
}
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("小明",2));
list.add(new Student("小费",3));
list.add(new Student("谁啊",6));
for (Student student : list) {
student= new Student("修改后",18);
}
System.out.println(list);
}
和预期结果不一致
[Student(name=小明, age=2), Student(name=小费, age=3), Student(name=谁啊, age=6)]
三、 将List集合中的每个对象属性更改为其他值(没问题)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student{
private String name;
private int age;
}
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("小明",2));
list.add(new Student("小费",3));
list.add(new Student("谁啊",6));
for (Student student : list) {
student.setName("小肥肥");
student.setAge(20);
}
System.out.println(list);
}
结果正确
[Student(name=小肥肥, age=20), Student(name=小肥肥, age=20), Student(name=小肥肥, age=20)]
那么你肯定有疑问这是为什么呢?
- 涉及到 Java 中的
引用传递和值传递的概念
。在 Java 中,基本数据类型(如 int、double 等)是按值传递的,而对象(包括字符串、自定义类等)是按引用传递的。- 当你将一个对象传递给方法或在循环中操作时,你实际上是在操作对象的引用,而不是对象本身。这意味着你可以通过引用来
修改对象的属性
,但不能修改对象的引用本身。
对象的引用传递意味着你可以在不改变引用的情况下修改对象的内容,但不能在引用级别改变对象的本身。而值传递则是基于对象的拷贝进行操作,不会影响原始对象。
四、 解决方案
第一种
使用Lsit中特有的方法set()
修改指定索引处元素
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for (int i = 0; i < list.size(); i++) {
list.set(i, "修改");
}
System.out.println(list);
}
结果正确
[修改, 修改]
第二种
使用了 Java 8 中的 Stream 来处理列表中的元素
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
List<String> updateList = list.stream().map(s -> s = "修改").collect(Collectors.toList());
System.out.println(updateList); //[修改, 修改, 修改, 修改]
System.out.println(list); //[a, b, c, d]
}
这里要明白updateList
和list
的区别
- 请注意,这里的 s 是一个临时变量,它只是流中元素的引用,
修改它并不会改变原始列表。
通过收集器将流中的元素收集到一个新的列表
中。- 因此,你得到的
updateList
列表实际上是由每个元素 “修改” 构成的新列表,而不是对原始列表中元素的修改。这是因为在 Stream API 中,操作是按照函数式编程的方式进行的,不会直接修改原始数据,而是创建新的数据流。