Java 将所选元素移动一次并返回其更新的索引
背景:Java 将所选元素移动一次并返回其更新的索引,java,java-8,java-stream,Java,Java 8,Java Stream,背景: public int[] moveUp(int[] selectedIndices) { Action[] array = concatenate(new Action[]{null}, actions.toArray(new Action[0])); for (int i = 0; i < selectedIndices.length; i++) { swap(array, selectedIndices[i] + 1, selectedIndic
public int[] moveUp(int[] selectedIndices) {
Action[] array = concatenate(new Action[]{null}, actions.toArray(new Action[0]));
for (int i = 0; i < selectedIndices.length; i++) {
swap(array, selectedIndices[i] + 1, selectedIndices[i]);
selectedIndices[i] -= 1;
}
actions = new ArrayList<>(this.actions.size());
for (Action action : array) {
if (action != null) {
actions.add(action);
}
}
return selectedIndices;
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.shazam</groupId>
<artifactId>shazamcrest</artifactId>
<version>0.11</version>
<scope>test</scope>
</dependency>
</dependencies>
/////////////////////////////////////////////////////////////////////////
public interface Action {
}
/////////////////////////////////////////////////////////////////////////
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
public class Actions {
private List<Action> actions = new ArrayList<>();
public void add(Action action) {
this.actions.add(action);
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
private static <T> void swap(List<T> list, int index, int index2) {
T t = list.get(index);
list.set(index, list.get(index2));
list.set(index2, t);
}
}
/////////////////////////////////////////////////////////////////////////
public class FakeAction implements Action {
@SuppressWarnings("FieldCanBeLocal") // used by shazamcrest
private final String name;
private FakeAction(String name) {
this.name = name;
}
static Actions actionsWithElements(int... elementsNames) {
Actions actions = new Actions();
for (int elementName : elementsNames) {
actions.add(new FakeAction(String.valueOf(elementName)));
}
return actions;
}
static int[] indices(int... indices) {
return indices;
}
}
/////////////////////////////////////////////////////////////////////////
import org.junit.Test;
import static com.shazam.shazamcrest.MatcherAssert.assertThat;
import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
import static FakeAction.actionsWithElements;
import static FakeAction.indices;
public class ActionsMoveUpTest {
@Test
public void movesUpSingleAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(2));
assertThat(actions, sameBeanAs(actionsWithElements(0, 2, 1, 3)));
}
@Test
public void movesUpMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(1, 3));
assertThat(actions, sameBeanAs(actionsWithElements(1, 0, 3, 2)));
}
@Test
public void doesNothingWhenArrayOfIndicesToMoveUpIsEmpty() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices());
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 3)));
}
@Test
public void doesNotLoseSelectionWhenMovingUpTheTopAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
int[] newIndices = actions.moveUp(indices(0));
assertThat(newIndices, sameBeanAs(indices(0)));
}
@Test
public void movesUpOnlyThoseActionsWhichAreNotOnTheTopAlready() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
actions.moveUp(indices(0, 1, 4, 6));
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 4, 3, 6, 5)));
}
@Test
public void doesNotLoseSelectionOfTheTopActionsWhenMovingMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
int[] newIndices = actions.moveUp(indices(0, 1, 4, 6));
assertThat(newIndices, sameBeanAs(indices(0, 1, 3, 5)));
}
}
我最近反编译了我的一个老项目,我丢失了它的源代码,并且正在重构我多年前写的所有这些糟糕的代码
我有一个由UI显示的项目列表,项目可以上下移动,允许多选。我有一个方法int[]moveUp(int[]selectedIndices)
,它更新模型并返回列表中移位元素的新索引(这样我可以在模型更改后更新UI)
selectedDices
来自JList#getselectedDices
,它保证排序顺序不重复
旧解决方案:
public int[] moveUp(int[] selectedIndices) {
Action[] array = concatenate(new Action[]{null}, actions.toArray(new Action[0]));
for (int i = 0; i < selectedIndices.length; i++) {
swap(array, selectedIndices[i] + 1, selectedIndices[i]);
selectedIndices[i] -= 1;
}
actions = new ArrayList<>(this.actions.size());
for (Action action : array) {
if (action != null) {
actions.add(action);
}
}
return selectedIndices;
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.shazam</groupId>
<artifactId>shazamcrest</artifactId>
<version>0.11</version>
<scope>test</scope>
</dependency>
</dependencies>
/////////////////////////////////////////////////////////////////////////
public interface Action {
}
/////////////////////////////////////////////////////////////////////////
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
public class Actions {
private List<Action> actions = new ArrayList<>();
public void add(Action action) {
this.actions.add(action);
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
private static <T> void swap(List<T> list, int index, int index2) {
T t = list.get(index);
list.set(index, list.get(index2));
list.set(index2, t);
}
}
/////////////////////////////////////////////////////////////////////////
public class FakeAction implements Action {
@SuppressWarnings("FieldCanBeLocal") // used by shazamcrest
private final String name;
private FakeAction(String name) {
this.name = name;
}
static Actions actionsWithElements(int... elementsNames) {
Actions actions = new Actions();
for (int elementName : elementsNames) {
actions.add(new FakeAction(String.valueOf(elementName)));
}
return actions;
}
static int[] indices(int... indices) {
return indices;
}
}
/////////////////////////////////////////////////////////////////////////
import org.junit.Test;
import static com.shazam.shazamcrest.MatcherAssert.assertThat;
import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
import static FakeAction.actionsWithElements;
import static FakeAction.indices;
public class ActionsMoveUpTest {
@Test
public void movesUpSingleAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(2));
assertThat(actions, sameBeanAs(actionsWithElements(0, 2, 1, 3)));
}
@Test
public void movesUpMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(1, 3));
assertThat(actions, sameBeanAs(actionsWithElements(1, 0, 3, 2)));
}
@Test
public void doesNothingWhenArrayOfIndicesToMoveUpIsEmpty() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices());
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 3)));
}
@Test
public void doesNotLoseSelectionWhenMovingUpTheTopAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
int[] newIndices = actions.moveUp(indices(0));
assertThat(newIndices, sameBeanAs(indices(0)));
}
@Test
public void movesUpOnlyThoseActionsWhichAreNotOnTheTopAlready() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
actions.moveUp(indices(0, 1, 4, 6));
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 4, 3, 6, 5)));
}
@Test
public void doesNotLoseSelectionOfTheTopActionsWhenMovingMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
int[] newIndices = actions.moveUp(indices(0, 1, 4, 6));
assertThat(newIndices, sameBeanAs(indices(0, 1, 3, 5)));
}
}
问题:
public int[] moveUp(int[] selectedIndices) {
Action[] array = concatenate(new Action[]{null}, actions.toArray(new Action[0]));
for (int i = 0; i < selectedIndices.length; i++) {
swap(array, selectedIndices[i] + 1, selectedIndices[i]);
selectedIndices[i] -= 1;
}
actions = new ArrayList<>(this.actions.size());
for (Action action : array) {
if (action != null) {
actions.add(action);
}
}
return selectedIndices;
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.shazam</groupId>
<artifactId>shazamcrest</artifactId>
<version>0.11</version>
<scope>test</scope>
</dependency>
</dependencies>
/////////////////////////////////////////////////////////////////////////
public interface Action {
}
/////////////////////////////////////////////////////////////////////////
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
public class Actions {
private List<Action> actions = new ArrayList<>();
public void add(Action action) {
this.actions.add(action);
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
private static <T> void swap(List<T> list, int index, int index2) {
T t = list.get(index);
list.set(index, list.get(index2));
list.set(index2, t);
}
}
/////////////////////////////////////////////////////////////////////////
public class FakeAction implements Action {
@SuppressWarnings("FieldCanBeLocal") // used by shazamcrest
private final String name;
private FakeAction(String name) {
this.name = name;
}
static Actions actionsWithElements(int... elementsNames) {
Actions actions = new Actions();
for (int elementName : elementsNames) {
actions.add(new FakeAction(String.valueOf(elementName)));
}
return actions;
}
static int[] indices(int... indices) {
return indices;
}
}
/////////////////////////////////////////////////////////////////////////
import org.junit.Test;
import static com.shazam.shazamcrest.MatcherAssert.assertThat;
import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
import static FakeAction.actionsWithElements;
import static FakeAction.indices;
public class ActionsMoveUpTest {
@Test
public void movesUpSingleAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(2));
assertThat(actions, sameBeanAs(actionsWithElements(0, 2, 1, 3)));
}
@Test
public void movesUpMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(1, 3));
assertThat(actions, sameBeanAs(actionsWithElements(1, 0, 3, 2)));
}
@Test
public void doesNothingWhenArrayOfIndicesToMoveUpIsEmpty() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices());
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 3)));
}
@Test
public void doesNotLoseSelectionWhenMovingUpTheTopAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
int[] newIndices = actions.moveUp(indices(0));
assertThat(newIndices, sameBeanAs(indices(0)));
}
@Test
public void movesUpOnlyThoseActionsWhichAreNotOnTheTopAlready() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
actions.moveUp(indices(0, 1, 4, 6));
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 4, 3, 6, 5)));
}
@Test
public void doesNotLoseSelectionOfTheTopActionsWhenMovingMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
int[] newIndices = actions.moveUp(indices(0, 1, 4, 6));
assertThat(newIndices, sameBeanAs(indices(0, 1, 3, 5)));
}
}
它既不干净,也不高效
问题:
public int[] moveUp(int[] selectedIndices) {
Action[] array = concatenate(new Action[]{null}, actions.toArray(new Action[0]));
for (int i = 0; i < selectedIndices.length; i++) {
swap(array, selectedIndices[i] + 1, selectedIndices[i]);
selectedIndices[i] -= 1;
}
actions = new ArrayList<>(this.actions.size());
for (Action action : array) {
if (action != null) {
actions.add(action);
}
}
return selectedIndices;
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.shazam</groupId>
<artifactId>shazamcrest</artifactId>
<version>0.11</version>
<scope>test</scope>
</dependency>
</dependencies>
/////////////////////////////////////////////////////////////////////////
public interface Action {
}
/////////////////////////////////////////////////////////////////////////
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
public class Actions {
private List<Action> actions = new ArrayList<>();
public void add(Action action) {
this.actions.add(action);
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
private static <T> void swap(List<T> list, int index, int index2) {
T t = list.get(index);
list.set(index, list.get(index2));
list.set(index2, t);
}
}
/////////////////////////////////////////////////////////////////////////
public class FakeAction implements Action {
@SuppressWarnings("FieldCanBeLocal") // used by shazamcrest
private final String name;
private FakeAction(String name) {
this.name = name;
}
static Actions actionsWithElements(int... elementsNames) {
Actions actions = new Actions();
for (int elementName : elementsNames) {
actions.add(new FakeAction(String.valueOf(elementName)));
}
return actions;
}
static int[] indices(int... indices) {
return indices;
}
}
/////////////////////////////////////////////////////////////////////////
import org.junit.Test;
import static com.shazam.shazamcrest.MatcherAssert.assertThat;
import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
import static FakeAction.actionsWithElements;
import static FakeAction.indices;
public class ActionsMoveUpTest {
@Test
public void movesUpSingleAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(2));
assertThat(actions, sameBeanAs(actionsWithElements(0, 2, 1, 3)));
}
@Test
public void movesUpMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(1, 3));
assertThat(actions, sameBeanAs(actionsWithElements(1, 0, 3, 2)));
}
@Test
public void doesNothingWhenArrayOfIndicesToMoveUpIsEmpty() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices());
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 3)));
}
@Test
public void doesNotLoseSelectionWhenMovingUpTheTopAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
int[] newIndices = actions.moveUp(indices(0));
assertThat(newIndices, sameBeanAs(indices(0)));
}
@Test
public void movesUpOnlyThoseActionsWhichAreNotOnTheTopAlready() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
actions.moveUp(indices(0, 1, 4, 6));
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 4, 3, 6, 5)));
}
@Test
public void doesNotLoseSelectionOfTheTopActionsWhenMovingMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
int[] newIndices = actions.moveUp(indices(0, 1, 4, 6));
assertThat(newIndices, sameBeanAs(indices(0, 1, 3, 5)));
}
}
如何以干净高效的方式实施
MCVE和测试:
public int[] moveUp(int[] selectedIndices) {
Action[] array = concatenate(new Action[]{null}, actions.toArray(new Action[0]));
for (int i = 0; i < selectedIndices.length; i++) {
swap(array, selectedIndices[i] + 1, selectedIndices[i]);
selectedIndices[i] -= 1;
}
actions = new ArrayList<>(this.actions.size());
for (Action action : array) {
if (action != null) {
actions.add(action);
}
}
return selectedIndices;
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.shazam</groupId>
<artifactId>shazamcrest</artifactId>
<version>0.11</version>
<scope>test</scope>
</dependency>
</dependencies>
/////////////////////////////////////////////////////////////////////////
public interface Action {
}
/////////////////////////////////////////////////////////////////////////
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
public class Actions {
private List<Action> actions = new ArrayList<>();
public void add(Action action) {
this.actions.add(action);
}
public int[] moveUp(int[] selectedIndices) {
List<Action> selectedActions = stream(selectedIndices).mapToObj(actions::get).collect(toList());
actions.add(0, null);
for (int selectedIndex : selectedIndices) {
swap(actions, selectedIndex + 1, selectedIndex);
}
actions.remove(null);
return selectedActions.stream().mapToInt(actions::indexOf).toArray();
}
private static <T> void swap(List<T> list, int index, int index2) {
T t = list.get(index);
list.set(index, list.get(index2));
list.set(index2, t);
}
}
/////////////////////////////////////////////////////////////////////////
public class FakeAction implements Action {
@SuppressWarnings("FieldCanBeLocal") // used by shazamcrest
private final String name;
private FakeAction(String name) {
this.name = name;
}
static Actions actionsWithElements(int... elementsNames) {
Actions actions = new Actions();
for (int elementName : elementsNames) {
actions.add(new FakeAction(String.valueOf(elementName)));
}
return actions;
}
static int[] indices(int... indices) {
return indices;
}
}
/////////////////////////////////////////////////////////////////////////
import org.junit.Test;
import static com.shazam.shazamcrest.MatcherAssert.assertThat;
import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
import static FakeAction.actionsWithElements;
import static FakeAction.indices;
public class ActionsMoveUpTest {
@Test
public void movesUpSingleAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(2));
assertThat(actions, sameBeanAs(actionsWithElements(0, 2, 1, 3)));
}
@Test
public void movesUpMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices(1, 3));
assertThat(actions, sameBeanAs(actionsWithElements(1, 0, 3, 2)));
}
@Test
public void doesNothingWhenArrayOfIndicesToMoveUpIsEmpty() {
Actions actions = actionsWithElements(0, 1, 2, 3);
actions.moveUp(indices());
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 3)));
}
@Test
public void doesNotLoseSelectionWhenMovingUpTheTopAction() {
Actions actions = actionsWithElements(0, 1, 2, 3);
int[] newIndices = actions.moveUp(indices(0));
assertThat(newIndices, sameBeanAs(indices(0)));
}
@Test
public void movesUpOnlyThoseActionsWhichAreNotOnTheTopAlready() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
actions.moveUp(indices(0, 1, 4, 6));
assertThat(actions, sameBeanAs(actionsWithElements(0, 1, 2, 4, 3, 6, 5)));
}
@Test
public void doesNotLoseSelectionOfTheTopActionsWhenMovingMultipleActions() {
Actions actions = actionsWithElements(0, 1, 2, 3, 4, 5, 6);
int[] newIndices = actions.moveUp(indices(0, 1, 4, 6));
assertThat(newIndices, sameBeanAs(indices(0, 1, 3, 5)));
}
}
1.8
1.8
朱尼特
朱尼特
4.12
测试
com.shazam
沙赞克雷斯特
0.11
测试
/////////////////////////////////////////////////////////////////////////
公共接口操作{
}
/////////////////////////////////////////////////////////////////////////
导入java.util.ArrayList;
导入java.util.List;
导入静态java.util.Arrays.stream;
导入静态java.util.stream.Collectors.toList;
公共集体诉讼{
私有列表操作=新建ArrayList();
公共无效添加(操作){
this.actions.add(action);
}
公共整数[]上移(整数[]已选整数){
List selectedActions=stream(selectedDices).mapToObj(actions::get).collect(toList());
actions.add(0,空);
for(int-selectedIndex:selectedDices){
交换(操作,selectedIndex+1,selectedIndex);
}
动作。删除(空);
返回selectedActions.stream().mapToInt(actions::indexOf.toArray();
}
专用静态无效交换(列表列表、整数索引、整数索引){
T=list.get(索引);
list.set(index,list.get(index2));
列表集(index2,t);
}
}
/////////////////////////////////////////////////////////////////////////
公共类FakeAction实现操作{
@SuppressWarnings(“FieldCanBeLocal”)//由shazamcrest使用
私有最终字符串名;
私有伪造操作(字符串名称){
this.name=名称;
}
静态动作动作开关元件(内部元件){
动作=新动作();
for(内部元素名称:元素名称){
actions.add(新的FakeAction(String.valueOf(elementName));
}
返回动作;
}
静态int[]索引(int…索引){
回报指数;
}
}
/////////////////////////////////////////////////////////////////////////
导入org.junit.Test;
导入静态com.shazam.shazamcrest.matcherasert.assertThat;
导入静态com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
导入静态FakeAction.ActionswitElements;
进口静态伪造指数;
公共类操作{
@试验
public void movesUpSingleAction(){
动作动作=动作开关(0,1,2,3);
行动.向上移动(指数(2));
资产(行动,相同的行为(行动,要素(0,2,1,3));
}
@试验
public void movesupmultiplereactions(){
动作动作=动作开关(0,1,2,3);
行动.向上移动(指数(1,3));
资产(行动,相同的行为(行动和要素(1,0,3,2));
}
@试验
“公共无效”不适用于将不确定项移动为空的情况(){
动作动作=动作开关(0,1,2,3);
actions.moveUp(index());
资产(行动,相同的行为(行动和要素(0,1,2,3));
}
@试验
打开操作()时,public void不会关闭Selection{
动作动作=动作开关(0,1,2,3);
int[]newindex=actions.moveUp(索引(0));
资产(新指数、sameBeanAs指数(0));
}
@试验
公共无效仅适用于已提交至TopalReady()的诉讼{
动作动作=动作开关(0、1、2、3、4、5、6);
行动.上移(指数(0,1,4,6));
资产(行动,相同的行为(行动和要素(0、1、2、4、3、6、5));
}
@试验
public void在移动multiplereactions()时不会关闭对操作的选择{
动作动作=动作开关(0、1、2、3、4、5、6);
int[]newindex=actions.moveUp(索引(0,1,4,6));
资产(新指数,sameBeanAs(指数(0,1,3,5));
}
}
由于您假设selectedDices
已排序,因此通过将索引与其在selectedDices
中的位置进行比较,可以轻松确定要向上移动哪些元素。如果索引高于其位置,则将移动关联的元素
public int[] moveUp(int[] selecteIndices) {
// this assumes that selectedIndices is sorted
int[] newSelection = IntStream.range(0, selectedIndices.length)
.map(x -> selectedIndices[x] > x ? selectedIndices[x] - 1 : selectedIndices[x])
.toArray();
IntStream.range(0, selectedIndices.length)
.filter(x -> selectedIndices[x] > x)
.map(x -> selectedIndices[x])
.forEachOrdered(i -> swap(actions, i - 1, i));
return newSelection;
}
为了最大限度地减少思考“索引中的索引”所花费的精神能量,您可以单独计算要移动的第一个元素。对我来说,这更清楚,但这是主观的:
public int[] moveUp(int[] selecteIndices) {
// this assumes that selecteIndices are sorted
// index of the first element to move up or actions.size() if nothing needs to move
int firstToMove = IntStream.range(0, selectedIndices.length)
.filter(x -> selectedIndices[x] > x)
.map(x -> selectedIndices[x])
.findFirst()
.orElse(actions.size());
int[] newSelection = Arrays.stream(selectedIndices)
.map(i -> i >= firstToMove ? i - 1 : i)
.toArray();
Arrays.stream(selectedIndices)
.filter(i -> i >= firstToMove)
.forEachOrdered(i -> swap(actions, i - 1, i));
return newSelection;
}
多亏了米莎的观察,我得到了更简单的东西 关键是如果
选择了dices[i]==i
,元素不会移动:
actions: [a, b, c, d, e, f, g, h, i]
index: 0 1 2 3 4 5 6 7 8
selectedIndices: [0, 1, 2, 5, 6, 8]
elements to move left: f g i
output: [a, b, c, d, f, g, e, i, h]
从这里,它可以通过O(m)
时间复杂度(其中m=selecteddinces.length
)轻松实现,如下所示:
我想这类问题属于我,因为“干净高效”是非常固执己见的。@SzymonStepniak干净-我同意,高效-不确定。最后一个流具有
O(n*m)
复杂性。我更多地把它看作一个问题“如何解决问题X”,而不是“你认为我解决问题X的方法怎么样”。谢谢你的想法:)