我需要你的一些示例代码帮助我找不到的情况。 我有一个简单的对象列表。我的班级是这样的:
class MyClass {
String str;
Integer intgr;
}
该列表包含以下元素:
[{a1 5}, {b2 3}, {g1 1}, {b5 1}, {c9 11}, {g2 3}, {d1 4}, {b3 19}... ... ...]
我需要检查字符串中是否有任何元素包含相同的前缀(这里后缀是最后一个字符)然后保留该元素在整数中具有更大的值。上面示例列表的预期输出将是:
[{a1 5}, {c9 11}, {g2 3}, {d1 4}, {b3 19}... ... ...]
字符串将具有唯一值,但可以在前缀中匹配。我在java中不是那么好。所以有人可以帮我解决这个问题吗?这是我正在尝试的代码,但获得IndexOutOfBoundsException
。此代码有错误,因此需要您的帮助。
谢谢!
int size = list.size();
for (int j = 0; j < size; j++) {
if (list.get(j).str.substring(0, list.get(j).str.length()-1).compareTo(list.get(j+1).str.substring(0, list.get(j+1).str.length()-1)) == 0) {
if (list.get(j).intgr > list.get(j+1).intgr)
list.remove(list.get(j+1));
size--;
else {
list.remove(list.get(j));
j--;
size--;
}
}
}
答案 0 :(得分:1)
您可以迭代您的元素集合,将它们添加到Map
中,将键(前缀)与值(对象)相关联。每次添加元素时,都要检查使用相同前缀存储的元素是否大于添加的元素。
为了有这种行为:
provides this: [{a1 5}, {b2 3}, {g1 1}, {b5 1}, {c9 11}, {g2 3}, {d1 4}, {b3 19}]
results this: [{a1 5}, {c9 11}, {g2 3}, {d1 4}, {b3 19}]
您可以实现以下内容:
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class TestSystemOut {
public static void main(final String[] a) {
List<MyObj> list = prepareList();
System.out.println("provides this: " + list);
Map<String, MyObj> map = new LinkedHashMap<String, MyObj>(); // if result order doesn't matter this can be a simple HashMap
String strTmp;
for (MyObj obj : list) {
strTmp = obj.str;
strTmp = strTmp.substring(0, strTmp.length() - 1);
if (map.get(strTmp) == null || map.get(strTmp).integer < obj.integer) {
map.remove(strTmp); // this could be removed if order of result doesn't matter
map.put(strTmp, obj);
}
}
list.clear();
list.addAll(map.values());
System.out.println("results this: " + list);
}
public static class MyObj {
String str;
Integer integer;
public MyObj(final String str, final Integer integer) {
super();
this.str = str;
this.integer = integer;
}
@Override
public String toString() {
return "{" + str + " " + integer + "}";
}
}
private static List<MyObj> prepareList() {
List<MyObj> list = new ArrayList<MyObj>();
list.add(new MyObj("a1", 5));
list.add(new MyObj("b2", 3));
list.add(new MyObj("g1", 1));
list.add(new MyObj("b5", 1));
list.add(new MyObj("c9", 11));
list.add(new MyObj("g2", 3));
list.add(new MyObj("d1", 4));
list.add(new MyObj("b3", 19));
return list;
}
}
答案 1 :(得分:0)
另一种(可能更容易阅读和调试)的方式是:
简单实施:
public class Test {
public static void main(String[] args) throws InterruptedException {
List<MyClass> list = Arrays.asList(new MyClass("a1", 5),
new MyClass("b2", 3),
new MyClass("g1", 1),
new MyClass("b5", 1),
new MyClass("c9", 11),
new MyClass("g2", 3),
new MyClass("d1", 4),
new MyClass("b3", 19));
Map<String, MyClass> map = new HashMap<String, MyClass>();
for (MyClass mc : list) {
MyClass current = map.get(mc.getLetter());
if (current == null || mc.intgr > current.intgr) {
map.put(mc.getLetter(), mc);
}
}
System.out.println(map);
}
static class MyClass {
String str;
Integer intgr;
MyClass(String str, Integer intgr) {
this.str = str;
this.intgr = intgr;
}
String getLetter() {
return str.substring(0,1);
}
@Override
public String toString() {
return "[" + str + " " + intgr + "]";
}
}
}
答案 2 :(得分:0)
/*
* For every string in the list, look at all strings in the
* list and compare the substring from 0 to length-1, if they
* match and the id is not the same as the current s (i.e. s and
* list.get(i) are at the same address) then remove that string.
*/
public ArrayList remdup(ArrayList<String> list) {
for (String s : list) {
for (int i=0; i<list.size();i++) {
if (s.substring(0, s.length()-1).compareTo(list.get(i).substring(0, list.get(i).length()-1)) == 0
&& list.indexOf(list.get(i)) != list.indexOf(s)) {
list.remove(list.get(i));
}
}
}
return list;
}
也许尝试一下,尚未测试,但认为它应该工作。如果它不能尝试使用与compareTo()不同的东西,可以使用equals()作为替代。
此外,您将获得IndexOutOfBoundsException,因为每次删除元素时都会减去大小,从而缩小搜索范围。你没有考虑到remove()会为你做这件事。
我会考虑使用Map来代替类。这样你就不必重新发明轮子了。
答案 3 :(得分:0)
您的代码存在两个问题。首先,当j == size - 1
(最后一次迭代)时,您正在调用list.get(j + 1),这是导致异常的原因。只需将循环条件更改为j < size - 1
,异常就会消失。 (或者,从j = 1
开始,并与前一个元素进行比较。)
其次,您只是将每个元素与其直接后继元素进行比较。根据你的描述,这听起来不像你想要做的那样。
我建议在单独的方法中捕获比较逻辑。它可能是MyClass
的一部分:
class MyClass {
String str;
Integer intgr;
/**
* Returns the relationship between this and another MyClass instance.
* The relationship can be one of three values:
* <pre>
* -1 - This object should be discarded and other kept
* 0 - There is no relationship between this and other
* 1 - This object should be kept and other discarded
* </pre>
*
* @param other The other instance to evaluate
*
* @return 0 if there is no relationship.
*/
public int relationTo(MyClass other) {
final String myPrefix = str.substring(0, str.length() - 1);
final String otherPrefix = other.str.substring(0, other.str.length() - 1);
if (myPrefix.equals(otherPrefix)) {
return intgr < other.intgr ? -1 : 1;
} else {
return 0;
}
}
}
(这很容易转换为一个带有两个参数的方法,这个参数可以在MyClass
之外。)然后你可以使用这个方法来决定保留什么。您需要进行双重迭代才能找到不相邻的对象:
int size = list.size();
for (int i = 0; i < size; ++i) {
final MyClass current = list.get(i);
for (int j = 0; j < i; ++j) {
final MyClass previous = list.get(j);
final int relation = previous.relationTo(current);
if (relation < 0) {
// remove previous (at index j)
list.remove(j);
--i;
--j;
--size;
} else if (relation > 0) {
// remove current (at index i)
list.remove(i);
--i;
--size;
break; // exit inner loop
}
// else current and previous don't share a prefix
}
}