从特定索引处的列表中删除元素
Remove elements from a List at a specific index
我正在尝试编写一种删除每组 4 个元素的第一个、第二个和第三个元素的方法。
它似乎根本不起作用。
有人可以帮忙吗?
public static void reduziereKommentare(List<String> zeilen) {
if (!zeilen.isEmpty()) {
if (zeilen.size() % 4 != 0) {
throw new RuntimeException("Illegal size " + zeilen.size() + " of list, must be divisible by 4.");
}
for (int i = 1; i <= zeilen.size() % 4; i++) {
zeilen.remove(i);
zeilen.remove(i + 1);
zeilen.remove(i + 2);
}
}
System.out.println(zeilen);
}
如评论中所述,删除元素会影响索引。每当我需要做这样的事情时,我要么使用 Iterator
,要么向后循环。:
for (int i = zeilen.size() - 4; i >= 0; i -= 4) {
zeilen.remove(i + 2);
zeilen.remove(i + 1);
zeilen.remove(i);
}
请注意,我每次迭代都从 i
中减去 4,所以我每次都返回完整的四个块。
另请注意,我首先删除了最大的索引元素。如果我在循环中使用 i
、i + 1
和 i + 2
,我会再次 运行 进入相同的问题。我也可以使用 i
3 次,但这更清楚。
我的看法...不需要大小先决条件检查,但如果它代表比此方法范围更广的错误,您可能仍想捕获它。
鉴于此测试代码...
// Test code
List<String> myList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
myList.add(String.valueOf(i));
}
'zeilen' 循环可以实现为...
// "before" diagnostics
System.out.println(zeilen);
// The 'zeilen' loop
for (int i = 0, limit = zeilen.size(); i < limit; i++) {
if ((i+1) % 4 > 0) zeilen.remove(i/4);
}
// "after" diagnostics
System.out.println(zeilen);
并生产
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[3, 7, 11, 15, 19]
适用于任何长度的列表,在列表中保留每个“第 4 个”元素。
还有几个测试用例:
Given Results in
[] []
[0,1] []
[0,1,2,3] [3]
[0,1,2,3,4] [3]
[0,1,2,3,4,5,6,7] [3,7]
[0,1,2,3,4,5,6,7,8] [3,7]
简单地将每四个项目添加到新列表并 return 不是更容易吗?这也将消除从列表中删除元素时可能涉及的任何重复复制。并且目标列表的大小可以适当地开始。
public static List<String> reduziereKommentare(List<String> zeilen) {
Objects.requireNonNull(zeilen);
List<String> zeilen1= new ArrayList<>(zeilen.size()/4);
for(int i = 3; i < zeilen.size(); i+=4) {
zeilen1.add(zeilen.get(i));
}
return zeilen1;
}
您也可以使用流。
zeilen = IntStream.iterate(3, i ->i < zeilen.size(), i->i+=4)
.mapToObj(zeilen::get).toList();
备注:
- 无论列表是否为空或者大小不能被[=12=整除],这都会起作用。它只会忽略额外的元素。
- 将结果分配给原始变量将导致旧列表被垃圾回收。
- 我只检查空参数,因为那会导致异常。当然,如果提醒用户尺寸很重要,只需重新添加其他支票即可。
您的代码示例使用列表数据类型 - List<String> zeilen
- 但您单独编写了一条注释,说明您是从数组开始的:
"I used the Arrays.asList() function to add elements to the list"
asList()
shows the input argument is an array, defined using varargs的签名:
public static <T> List<T> asList(T... a)
因此,您将从这样的事情开始:
// rely on automatic array creation via varargs
List<String> list = Arrays.asList("one", "two", "three");
或来自显式数组,如下所示:
String[] strings = {"one", "two", "three"};
List<String> list = Arrays.asList(strings);
这是您当前解决方案的更完整图片:
- 从数组开始 –
String[]
– 显式创建它或依赖于通过可变参数自动创建数组
- 使用
Arrays.asList()
从该数组创建一个 List<String>
- 一次跳过三个项目遍历列表,只保留每四个项目(因此:第 4、8、12、16 等)
因为起点是一个字符串数组,并且知道你是
有兴趣只保留每 4 个元素,
你可以:
- 创建一个新的空
java.util.List<String>
- 迭代数组的每个元素
- 每第 4 个、第 8 个等元素,将其添加到最终结果列表中;忽略其他一切
这是执行此操作的代码:
private static List<String> buildListOfEveryFourthElement(String[] array) {
List<String> everyFourthElement = new ArrayList<>();
if (array != null) {
// start from "1", a bit easier to reason about "every 4th element"?
int current = 1;
for (String s : array) {
if (current > 1 && current % 4 == 0) {
everyFourthElement.add(s);
}
current++;
}
}
return everyFourthElement;
}
我省略了输入是否能被 4 整除的检查,但是你可以很容易地编辑第一个 if
语句
包括:if (array != null && array.length % 4 == 0) { .. }
这种“随手构建列表”方法的好处(相对于使用起始数组调用 Arrays.asList()
)
是原始输入数组不会以任何方式与结果列表相关联。
那又怎样?正如您在其中一条评论中提到的那样,您发现这是不允许的
修改列表——调用 .remove()
将抛出 java.lang.UnsupportedOperationException
。
请注意,如果您尝试 add()
某些内容到列表中,也会发生这种情况。
为什么会抛出异常?
因为 asList()
returns a java.util.List
由输入数组支持,这意味着列表和数组是
有点绑在一起。如果它允许您从(或向)
list 然后它还必须自动更新支持 array,他们没有那样实现。
这是来自 asList()
Javadoc 的简短片段:
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)
通过创建一个新列表并沿途填充它,您可以稍后在代码中自由修改该列表
通过删除或添加元素,对整个事物进行排序等。您还将避免对数组进行任何更改
在列表中显示为(可能令人惊讶的)变化——因为
该列表由数组支持,数组元素的更改将在关联列表中可见。
我正在尝试编写一种删除每组 4 个元素的第一个、第二个和第三个元素的方法。 它似乎根本不起作用。 有人可以帮忙吗?
public static void reduziereKommentare(List<String> zeilen) {
if (!zeilen.isEmpty()) {
if (zeilen.size() % 4 != 0) {
throw new RuntimeException("Illegal size " + zeilen.size() + " of list, must be divisible by 4.");
}
for (int i = 1; i <= zeilen.size() % 4; i++) {
zeilen.remove(i);
zeilen.remove(i + 1);
zeilen.remove(i + 2);
}
}
System.out.println(zeilen);
}
如评论中所述,删除元素会影响索引。每当我需要做这样的事情时,我要么使用 Iterator
,要么向后循环。:
for (int i = zeilen.size() - 4; i >= 0; i -= 4) {
zeilen.remove(i + 2);
zeilen.remove(i + 1);
zeilen.remove(i);
}
请注意,我每次迭代都从 i
中减去 4,所以我每次都返回完整的四个块。
另请注意,我首先删除了最大的索引元素。如果我在循环中使用 i
、i + 1
和 i + 2
,我会再次 运行 进入相同的问题。我也可以使用 i
3 次,但这更清楚。
我的看法...不需要大小先决条件检查,但如果它代表比此方法范围更广的错误,您可能仍想捕获它。
鉴于此测试代码...
// Test code
List<String> myList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
myList.add(String.valueOf(i));
}
'zeilen' 循环可以实现为...
// "before" diagnostics
System.out.println(zeilen);
// The 'zeilen' loop
for (int i = 0, limit = zeilen.size(); i < limit; i++) {
if ((i+1) % 4 > 0) zeilen.remove(i/4);
}
// "after" diagnostics
System.out.println(zeilen);
并生产
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[3, 7, 11, 15, 19]
适用于任何长度的列表,在列表中保留每个“第 4 个”元素。
还有几个测试用例:
Given Results in
[] []
[0,1] []
[0,1,2,3] [3]
[0,1,2,3,4] [3]
[0,1,2,3,4,5,6,7] [3,7]
[0,1,2,3,4,5,6,7,8] [3,7]
简单地将每四个项目添加到新列表并 return 不是更容易吗?这也将消除从列表中删除元素时可能涉及的任何重复复制。并且目标列表的大小可以适当地开始。
public static List<String> reduziereKommentare(List<String> zeilen) {
Objects.requireNonNull(zeilen);
List<String> zeilen1= new ArrayList<>(zeilen.size()/4);
for(int i = 3; i < zeilen.size(); i+=4) {
zeilen1.add(zeilen.get(i));
}
return zeilen1;
}
您也可以使用流。
zeilen = IntStream.iterate(3, i ->i < zeilen.size(), i->i+=4)
.mapToObj(zeilen::get).toList();
备注:
- 无论列表是否为空或者大小不能被[=12=整除],这都会起作用。它只会忽略额外的元素。
- 将结果分配给原始变量将导致旧列表被垃圾回收。
- 我只检查空参数,因为那会导致异常。当然,如果提醒用户尺寸很重要,只需重新添加其他支票即可。
您的代码示例使用列表数据类型 - List<String> zeilen
- 但您单独编写了一条注释,说明您是从数组开始的:
"I used the Arrays.asList() function to add elements to the list"
asList()
shows the input argument is an array, defined using varargs的签名:
public static <T> List<T> asList(T... a)
因此,您将从这样的事情开始:
// rely on automatic array creation via varargs
List<String> list = Arrays.asList("one", "two", "three");
或来自显式数组,如下所示:
String[] strings = {"one", "two", "three"};
List<String> list = Arrays.asList(strings);
这是您当前解决方案的更完整图片:
- 从数组开始 –
String[]
– 显式创建它或依赖于通过可变参数自动创建数组 - 使用
Arrays.asList()
从该数组创建一个 - 一次跳过三个项目遍历列表,只保留每四个项目(因此:第 4、8、12、16 等)
List<String>
因为起点是一个字符串数组,并且知道你是 有兴趣只保留每 4 个元素, 你可以:
- 创建一个新的空
java.util.List<String>
- 迭代数组的每个元素
- 每第 4 个、第 8 个等元素,将其添加到最终结果列表中;忽略其他一切
这是执行此操作的代码:
private static List<String> buildListOfEveryFourthElement(String[] array) {
List<String> everyFourthElement = new ArrayList<>();
if (array != null) {
// start from "1", a bit easier to reason about "every 4th element"?
int current = 1;
for (String s : array) {
if (current > 1 && current % 4 == 0) {
everyFourthElement.add(s);
}
current++;
}
}
return everyFourthElement;
}
我省略了输入是否能被 4 整除的检查,但是你可以很容易地编辑第一个 if
语句
包括:if (array != null && array.length % 4 == 0) { .. }
这种“随手构建列表”方法的好处(相对于使用起始数组调用 Arrays.asList()
)
是原始输入数组不会以任何方式与结果列表相关联。
那又怎样?正如您在其中一条评论中提到的那样,您发现这是不允许的
修改列表——调用 .remove()
将抛出 java.lang.UnsupportedOperationException
。
请注意,如果您尝试 add()
某些内容到列表中,也会发生这种情况。
为什么会抛出异常?
因为 asList()
returns a java.util.List
由输入数组支持,这意味着列表和数组是
有点绑在一起。如果它允许您从(或向)
list 然后它还必须自动更新支持 array,他们没有那样实现。
这是来自 asList()
Javadoc 的简短片段:
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)
通过创建一个新列表并沿途填充它,您可以稍后在代码中自由修改该列表 通过删除或添加元素,对整个事物进行排序等。您还将避免对数组进行任何更改 在列表中显示为(可能令人惊讶的)变化——因为 该列表由数组支持,数组元素的更改将在关联列表中可见。