所以,我有一个问题,如下面的 ArrayList 中存在特定类型的各种对象,
...
//Class definition
class Params
{
long startTimeMillis;
long endTimeMillis;
String currentState;
.. correponding getters and setters are present here ..
}
....
ArrayList<Params> activities=new ArrayList<>();
Params h1= new Params();
h1.setStartTimeMillis(1435939200000L);//"16:00"
h1.setEndTimeMillis(1435941000000L);//"16:30"
h1.setCurrentState("C");
Params h2= new Params();
h2.setStartTimeMillis(1435941000000L);//"16:30"
h2.setEndTimeMillis(1435941900000L);//"16:45"
h2.setCurrentState("B");
Params h3= new Params();
h3.setStartTimeMillis(1435941900000L);//"16:45"
h3.setEndTimeMillis(1435942500000L);//"16:55"
h3.setCurrentState("A");
Params h4= new Params();
h4.setStartTimeMillis(1435942500000L);//"16:55"
h4.setEndTimeMillis(1435942800000L);//"17:00"
h4.setCurrentState("B");
Params h5= new Params();
h5.setStartTimeMillis(1435942800000L);//"17:00"
h5.setEndTimeMillis(1435943400000L);//"17:10"
h5.setCurrentState("C");
activities.add(h1);
activities.add(h2);
activities.add(h3);
activities.add(h4);
activities.add(h5);
现在,我可以增加或减少各种情况:
e.g。
示例1:
以防我修改对象h2
,使h2
( 16:30 )的开始时间减少10分钟,然后结束时间h1
应该减少相同的h1
结束时间 16:20
示例2:
以防我修改对象h2
,使h2
( 16:45 )的结束时间增加10分钟,即 16:55 然后,对象h3
应该从列表中移除,因为h2
完全占用了对象。{/ p>
I / P: 我总是在两个diff变量中为每个对象修改了开始和结束时间,但问题是在运行时修改上述情况中提到的对象并相应地更新arraylist。
答案 0 :(得分:2)
正确的方法是使用TreeSet
并定义Param
的排序。为此,您必须Param
实施Comparable
,然后同时提供hashCode
和equals
的实施。
然后,您可以修改项目,然后导航该集合以查找前一项和后一项。我的解决方案假设没有任何重叠时间,它也会处理你的第二个案例(删除无效的时间片)。
首先,我们需要Param
实施Comparable<Param>
:
public class Param implements Comparable<Param> {
//Public just for demo purposes and brevity
public int start;
public int end;
public Param(int start, int end) {
this.start = start;
this.end = end;
}
@Override
public int compareTo(Param o) {
//Needs to be consistent with equals!!
int result = this.start - o.start;
if(result == 0) {
result = (this.end - this.start) - (o.end - o.start);
}
return result;
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + start;
result = 31 * result + end;
return result;
}
@Override
public boolean equals(Object o) {
... // null check, reference check etc.
Param p = (Param) o;
return this.start == p.start && this.end == p.end;
}
}
现在所有的努力都已完成!您可以使用TreeSet
中的方法查找正确的项目,然后进行修改。这是一些示例代码。
NavigableSet<Param> pset = new TreeSet<Param>();
Param p1 = new Param(10, 20);
Param p2 = new Param(20, 30);
Param p3 = new Param(30, 50);
Param p4 = new Param(50, 60);
pset.add(p1);
pset.add(p2);
pset.add(p3);
pset.add(p4);
System.out.println(pset);
int sdiff = -2;
int ediff = 2;
//Find the item we want, as well as the preceding and succeeding items
Param p = pset.floor(new Param(20, 30));
Param lower = pset.lower(p);
Param higher = pset.higher(p);
//Remove the item from the set and modify it
pset.remove(p);
p.start += sdiff;
p.end += ediff;
//Add only if it is valid
if(p.start < p.end) {
pset.add(p);
}
//If we have a preceding item
if(lower != null) {
//Remove, modify, and add back to set
pset.remove(lower);
lower.end += sdiff;
if(lower.start < lower.end) {
pset.add(lower);
}
}
//Same case as lower
if(higher != null) {
pset.remove(higher);
higher.start += ediff;
if(higher.start < higher.end) {
pset.add(higher);
}
}
System.out.println(pset);
运行此代码会给我们:
[[10, 20], [20, 30], [30, 50], [50, 60]]
[[10, 22], [22, 28], [28, 50], [50, 60]]
此代码适用于无效的时间片,以下示例将演示:
int sdiff = -20;
int ediff = 20;
输出:
[[10, 20], [20, 30], [30, 50], [50, 60]]
[[0, 50], [50, 60]]
如果您以时间片无效的方式修改了元素本身,它也会起作用:
int sdiff = 5;
int ediff = -5;
Param p = pset.floor(new Param(10, 20));
给我们:
[[10, 20], [20, 30], [30, 50], [50, 60]]
[[15, 30], [30, 50], [50, 60]]
和
int sdiff = 5;
int ediff = -10;
Param p = pset.floor(new Param(10, 20));
给我们:
[[10, 20], [20, 30], [30, 50], [50, 60]]
[[10, 30], [30, 50], [50, 60]]
如果您修改元素以跨越多个切片,则此特定解决方案无法工作。但稍作修改,你也可以让它来处理这些情况。这是使用排序结构真正有用的地方,因为使用列表执行此操作将是一种噩梦。修改涉及使用while
循环而不是if
并且只要存在需要修改的元素就会遍历循环。循环还检查我们是否最终进入&#34;中间&#34;切片,如果是这样,它会适当地调整开始/结束时间:
//As long as we have elements to modify
while(lower != null) {
Param nextLower = null;
//Remove, modify, and add back to set if valid
pset.remove(lower);
lower.end += sdiff;
if(lower.start < lower.end) {
//The modified slice is valid, so add it back
pset.add(lower);
} else if(lower.start > lower.end) {
//The modified slice is not valid and so we're not
//going to add it. But it looks like we might have
//encroached on the space of the slice that precedes
//"lower" (at least; we may have extended past even
//more, possibly all the way up to and past the
//beginning)
nextLower = pset.lower(p);
if(nextLower != null && p.start == nextLower.start) {
//It looks like we took up the space of the preceding
//slice exactly (i.e., we are flush against it) and
//so we don't need to do anything.
nextLower = null;
} else if(nextLower != null) {
//It looks like we took up the space of the preceding
//slice and then some. Let's adjust sdiff to reflect
//that.
sdiff = p.start - nextLower.end;
}
}
lower = nextLower;
}
//Similar to lower
while(higher != null) {
Param nextHigher = null;
pset.remove(higher);
higher.start += ediff;
//Need to check for the additional case where the modified element's
//end time could supersede a "higher" element's end time.
if(higher.start < higher.end && higher.end > p.end) {
pset.add(higher);
} else if(higher.start > higher.end || higher.end <= p.end) {
nextHigher = pset.higher(p);
if(nextHigher != null && p.end == nextHigher.start) {
nextHigher = null;
} else if(nextHigher != null) {
ediff = p.end - nextHigher.start;
}
}
higher = nextHigher;
}
例如,如果您将[30, 40]
更改为[0, 5]
或[5, 15]
,则此算法无法运行。在这种情况下,您最终会得到[30, 40]
曾经存在的空间,并且没有明确定义该空间应该如何填充。 [20, 30]
应该更改为[20, 40]
,还是[40, 50]
更改为[30, 50]
?或者像[20, 35]
和[35, 50]
这样的内容呢?只要修改后的范围包含全部或部分原始范围,该算法就可以工作。
答案 1 :(得分:0)
这将修改您的开始时间
public void modifyStart(Params toModify,int increment,ArrayList<Params> list){
int index = list.indexOf(toModify);
int timeStart=toModify.getStartTimeMillis()+increment;
toModify.setStartTimeMillis(timeStart);
for(int i=index-1;i>=0;i--){ //removing all previous
if(timeStart<list.get(i).getStartTimeMillis()){
list.remove(i);
index--;
}else{
break;
}
}
if(index==0){
return;
}
Params previous = list.get(index-1);
previous.setEndTimeMillis(previous.getEndTimeMillis()+increment);
if(toModify.getStartTimeMillis()>toModify.getEndTimeMillis()){ //removes yourself
list.remove(toModify);
}
}
结束时间非常相似
注意:没有经过测试,只是显示了一个想法