我正在尝试创建一个编辑器来编辑在JTree中选择的多个设备。
如果Collection中的项目对于某个字段都具有相同的值,我将在编辑器表单中显示该值。如果它们具有不同的值,我将显示“多个值”
我试图利用这样的东西,但仅限于比较两个项目。我想为集合中的所有项目执行此操作。
private static List<String> difference(Student s1, Student s2) {
List<String> values = new ArrayList<>();
for (Field field : s1.getClass().getDeclaredFields()) {
// You might want to set modifier to public first (if it is not public yet)
field.setAccessible(true);
Object value1 = field.get(s1);
Object value2 = field.get(s2);
if (value != null && value != null) {
System.out.println(field.getName() + "=" + value1);
System.out.println(field.getName() + "=" + value2);
if (!Objects.equals(value1, value2) {
values.add(value2);
}
}
}
return values;
}
有人可以举例说明如何确定集合中对象具有相同值的字段吗?
我的哈希和等于代码如下。我假设这可以使用内置的Collection方法完成,但我很欣赏一个例子。
@Override
public int hashCode() {
int hash = 5;
hash = 47 * hash + (this.isSelected ? 1 : 0);
hash = 47 * hash + Objects.hashCode(this.user);
hash = 47 * hash + Objects.hashCode(this.password);
hash = 47 * hash + Objects.hashCode(this.address);
hash = 47 * hash + (int) (this.addressAsLong ^ (this.addressAsLong >>> 32));
hash = 47 * hash + this.port;
hash = 47 * hash + Objects.hashCode(this.vendor);
hash = 47 * hash + Objects.hashCode(this.model);
hash = 47 * hash + Objects.hashCode(this.OS);
hash = 47 * hash + Objects.hashCode(this.description);
hash = 47 * hash + Objects.hashCode(this.version);
hash = 47 * hash + Objects.hashCode(this.hostName);
hash = 47 * hash + Objects.hashCode(this.domain);
hash = 47 * hash + Objects.hashCode(this.deviceType);
hash = 47 * hash + Objects.hashCode(this.Location);
hash = 47 * hash + Objects.hashCode(this.SerialNumber);
// hash = 47 * hash + Objects.hashCode(this.parent);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DefaultDevice other = (DefaultDevice) obj;
if (this.isSelected != other.isSelected) {
System.out.println("isSelected");
return false;
}
if (this.addressAsLong != other.addressAsLong) {
// System.out.println("long");
return false;
}
if (this.port != other.port) {
//System.out.println("port");
return false;
}
if (!Objects.equals(this.user, other.user)) {
// System.out.println("user");
return false;
}
if (!Objects.equals(this.password, other.password)) {
//System.out.println("pass");
return false;
}
if (!Objects.equals(this.vendor, other.vendor)) {
//System.out.println("ven");
return false;
}
if (!Objects.equals(this.model, other.model)) {
//System.out.println("mod");
return false;
}
if (!Objects.equals(this.OS, other.OS)) {
// System.out.println("os");
return false;
}
if (!Objects.equals(this.description, other.description)) {
//System.out.println("des");
return false;
}
if (!Objects.equals(this.version, other.version)) {
//System.out.println("ver");
return false;
}
if (!Objects.equals(this.hostName, other.hostName)) {
// System.out.println("hostNa");
return false;
}
if (!Objects.equals(this.domain, other.domain)) {
// System.out.println("dom");
return false;
}
if (!Objects.equals(this.deviceType, other.deviceType)) {
// System.out.println("dt");
return false;
}
if (!Objects.equals(this.Location, other.Location)) {
//System.out.println("loc");
return false;
}
if (!Objects.equals(this.SerialNumber, other.SerialNumber)) {
// System.out.println("sn");
return false;
}
return true;
}
答案 0 :(得分:1)
考虑到可访问性,使用getter / setter而不是字段访问等的综合解决方案需要相当多的努力,但在您所描述的范围内,算法可能如下所示:
Map<String, Object>
替换那些)在代码中它看起来像这样:
class ObjectMatcher {
// NPE on null items
// assumes public default constructor for T is available
public <T> T match(Collection<T> items, T defaults) {
if (items.isEmpty()) {
return defaults;
}
try {
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) items.iterator().next().getClass();
Field[] fields = clazz.getDeclaredFields();
T res = clazz.newInstance();
for (Field field : fields) {
boolean firstItem = true;
Object match = null;
for (T item : items) {
Object value = field.get(item);
if (firstItem) {
match = value;
}
else if (!Objects.equals(value, match)) {
match = field.get(defaults);
break;
} // otherwise keep the match as is
firstItem = false;
}
field.set(res, match);
}
return res;
}
catch (IllegalAccessException | InstantiationException e) {
throw new RuntimeException(e);
}
}
}
这是一个简单的测试,用于场不匹配,匹配和null /非null不匹配的情况:
@Test
public void match_onMistmatchMatchAndNull_ok() {
Student s1 = new Student("Andrew", "Physics", null);
Student s2 = new Student("Joe", "Physics", 3.45);
Student s3 = new Student("Nicki", "Physics", 2.39);
Student defaults = new Student("Multiple Names", "Multiple Courses", 1.0);
ObjectMatcher matcher = new ObjectMatcher();
Student res = matcher.match(Arrays.asList(s1, s2, s3), defaults);
assertEquals("Multiple Names", res.name);
assertEquals("Physics", res.course);
assertEquals(1.0, res.grade.doubleValue(), 0.001);
}
您可以在dedicated GitHub repo上找到测试类的完整代码。