Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何连接两组对象_Java - Fatal编程技术网

Java 如何连接两组对象

Java 如何连接两组对象,java,Java,我有两组对象,每一组的对象中都有一个公共的“键”。我想要一个结果集/列表,它将具有多个属性的连接。 比如说, 设置一个:[{id:1,姓名:john,年龄:22},{..}] 集合B:[{id:1,电话:1234,类型:mobile},{..}] 设置结果:[{id:1,姓名:john,年龄:22,电话:1234,类型:mobile},{..}] 在不使用循环或不将集合转换为Hashmap的情况下可以实现这一点吗? 谢谢。我假设您的集合只是两个Java集合的可视化表示: Set<User&

我有两组对象,每一组的对象中都有一个公共的“键”。我想要一个结果集/列表,它将具有多个属性的连接。 比如说,

设置一个:
[{id:1,姓名:john,年龄:22},{..}]

集合B:
[{id:1,电话:1234,类型:mobile},{..}]

设置结果:
[{id:1,姓名:john,年龄:22,电话:1234,类型:mobile},{..}]

在不使用循环或不将集合转换为Hashmap的情况下可以实现这一点吗?
谢谢。

我假设您的
集合
只是两个Java
集合
的可视化表示:

Set<User>
Set<Phone>
现在只需执行以下代码:

for (User u : users) {
    usersWithPhone.put(u.id, new UserWithPhone(u));
}
for (Phone p : phones) {
    usersWithPhone.get(p.id).setPhoneDetails(p);
}

其中
usersWithPhone
是一个
Map
。好。。。我知道这不是你想要的。。。我的意思是有循环,地图。。。但这是我们在Java中如何做到的…

因此,看起来您对循环的关注更多的是为了避免暴力方法,而不是实际使用循环

这里有一个想法,但它要求您的集合必须预先排序,否则就无法合并集合而不进行多次迭代

假设你有两套:用户和电话

users =  [{1, "john"}, {2, "ken"}]
phones = [{2, "555-1234"}, {4, "234-23424"}]
您可以做的是在每个集合的当前id不同时“迭代”它们。这里重要的一点是只迭代id低于另一个id的集合,因此如果用户中的id很小,则在用户集合中行走,如果电话集合中的id较低,则在电话集合中行走。通过这种方式,您不会对每个集合进行多次迭代,但最多迭代N次,其中N是用户集合的长度

因此,在本例中,您从id:1和2开始

 users[0].id == 1
 phones[0].id == 2
因为它们是不同的,所以在用户索引上移动

 users[1].id == 2
 phones[0].id == 2
现在他们是一样的。。。在这种情况下,您将合并对象并创建一个新的
联系人

现在,您可以在两个索引上移动并重复,除非您在其中一个集合的末尾,在这种情况下,您就完成了

基本上类似于这个伪代码

// while the id's are different 
while( users[usersIndex].id != phones[phoneIndex].id ) {
    if (user.id < phone.id) { usersIndex++ );
    if (phone.id < user.id) { phoneIndex++ );
}
// At this point either they are the same ... OR one we are at the end of one of the collections
if (user.id == phone.id ) { result.add( new Contact(user, phone) );}
else { we are done }

... repeat. 
在这一点上,你可能会想“是的,这一切都很好,但我怎么知道它是有效的?”

下面是代码,合并两个集合而不迭代超过N倍的集合,并用结果创建一个新集合

在本例中,我使用Lombok注释。。。因为它很棒,它基本上为您创建了getter/setter、toString()、equals和hashCode方法,所以您不必编写它们

package merge;

import lombok.Builder;
import lombok.Data;

import java.util.Set;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        Merge m = new Merge();
        System.out.println("Result= " +
                        m.merge(
                                buildUsers(),
                                buildPhones(),
                                new TreeSet<>()
                        )
        );
    }

    private static Set<User> buildUsers() {
        Set<User> users = new TreeSet<>();
        users.add(new User(1, "j"));
        users.add(new User(3, "k"));
        return users;

    }

    private static Set<Phone> buildPhones() {
        Set<Phone> phones = new TreeSet<>();
        phones.add(new Phone(1, "123"));
        phones.add(new Phone(2, "345"));
        phones.add(new Phone(3, "678"));
        return phones;
        /// KEEP SCROLLING
    }
}

class Merge {
    public Set<Contact> merge(Set<User> users, Set<Phone> phones, Set<Contact> contacts) {

        if (users.isEmpty() || phones.isEmpty()) {
            return contacts;
        }

        User user = users.iterator().next();
        Phone phone = phones.iterator().next();

        if (user.getId() == phone.getId()) {
            addContact(contacts, user, phone);
            users.remove(user);
            phones.remove(phone);
        } else if (user.getId() < phone.getId()) {
            users.remove(user);
        } else {
            phones.remove(phone);
        }

        return merge(users, phones, contacts);
    }

    private boolean addContact(Set<Contact> contacts, User user, Phone phone) {
        return contacts.add(Contact.builder()
                .id(user.getId())
                .name(user.getName())
                .phone(phone.getPhone())
                .build());
    }
}

@Data
class User implements Comparable<User> {
    private final int id;
    private final String name;

    @Override
    public int compareTo(User o) {
        return Integer.compare(this.id, o.id);
    }
}

@Data
class Phone implements Comparable<Phone> {
    final int id;
    final String phone;

    @Override
    public int compareTo(Phone o) {
        return Integer.compare(this.id, o.id);
    }
}

@Data
@Builder
class Contact implements Comparable<Contact> {
    int id;
    String name;
    String phone;

    @Override
    public int compareTo(Contact o) {
        return Integer.compare(this.id, o.id);
    }
}

“不使用循环就可以实现这一点”。一个响亮的否定。你对循环有什么担心?有趣的事实是,如果你是一个HashSet(或它的孩子),它与HashMap完全相同。(只需查看源代码)。那么你为什么不想换成HashMap呢?(两次投票?真的吗?)这些集合的内容是什么?我的意思是,这些物体有哪种类型?(看起来它们类似于
Map
)。当您不知道对象的类型,并且根本不知道如何“合并”它们时,就根本不会出现关于循环的问题。(@boristesspider…或关于递归的问题;-))生成的
equals
hashCode
equals
不太一致;这并不理想,但也不太重要,除非OP希望
Set
删除具有不同名称的重复用户ID。我会避免变异
集合
,而采用更具功能性的方法(如您建议的
ConsList
pseudocode)-使用
TreeSet.tailSet(item,false)
。与
比较一致你的意思是?你是对的,我认为应该有一种方法使它保持一致,可能不会使
字符串
属性成为最终属性?关于改变集合,我同意你的观点,我最初尝试传递迭代器,但当我在验证其空性时遇到问题时,我记得这是一个概念证明,而不是一个准备生产的代码,然后从集合中删除项,以使我的算法能够正常实现。我想看看
TreeSet.tailSet
是的,我的意思是“您的
比较将与生成的
equals
hashCode
不太一致”。我将添加
@EqualsAndHashcode(of=“id”)
以将
equals
限制为仅包含
id
属性,但这实际上取决于OP对这些对象的行为的确切预期。您可以使用
NavigableSet.first()
NavigableSet.tailSet
,生成的代码应该与您的消费者几乎相同。非常感谢。它帮助我理解了如何解决这个问题。你说的“对循环的暴力关注”是对的
merge( users, phones, results ) {

    // base case, if one of them is empty
    // we're done
    if users.isEmpty() OR phones.isEmpty() 
         return results

    // take the first element on each set and compare them
    user = users.head
    phone = phones.head

    // if they're the same create a new contact and remove them
    if user.id == phone.id 
       results.add( new Contact(user, phone))
       users.remove(user) 
       phones.remove(phone)

    // iterate on the users set
    if user.id < phone.id 
       // we won't find a matching phone
      users.remove(user)

    // iterate on the phone set
    if phone.id < user.id
       // we won't find a matching user
       phones.remove(phone)

    // call again with the modified sets
    return merge(users, phones, results)
}
package merge;

import lombok.Builder;
import lombok.Data;

import java.util.Set;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        Merge m = new Merge();
        System.out.println("Result= " +
                        m.merge(
                                buildUsers(),
                                buildPhones(),
                                new TreeSet<>()
                        )
        );
    }

    private static Set<User> buildUsers() {
        Set<User> users = new TreeSet<>();
        users.add(new User(1, "j"));
        users.add(new User(3, "k"));
        return users;

    }

    private static Set<Phone> buildPhones() {
        Set<Phone> phones = new TreeSet<>();
        phones.add(new Phone(1, "123"));
        phones.add(new Phone(2, "345"));
        phones.add(new Phone(3, "678"));
        return phones;
        /// KEEP SCROLLING
    }
}

class Merge {
    public Set<Contact> merge(Set<User> users, Set<Phone> phones, Set<Contact> contacts) {

        if (users.isEmpty() || phones.isEmpty()) {
            return contacts;
        }

        User user = users.iterator().next();
        Phone phone = phones.iterator().next();

        if (user.getId() == phone.getId()) {
            addContact(contacts, user, phone);
            users.remove(user);
            phones.remove(phone);
        } else if (user.getId() < phone.getId()) {
            users.remove(user);
        } else {
            phones.remove(phone);
        }

        return merge(users, phones, contacts);
    }

    private boolean addContact(Set<Contact> contacts, User user, Phone phone) {
        return contacts.add(Contact.builder()
                .id(user.getId())
                .name(user.getName())
                .phone(phone.getPhone())
                .build());
    }
}

@Data
class User implements Comparable<User> {
    private final int id;
    private final String name;

    @Override
    public int compareTo(User o) {
        return Integer.compare(this.id, o.id);
    }
}

@Data
class Phone implements Comparable<Phone> {
    final int id;
    final String phone;

    @Override
    public int compareTo(Phone o) {
        return Integer.compare(this.id, o.id);
    }
}

@Data
@Builder
class Contact implements Comparable<Contact> {
    int id;
    String name;
    String phone;

    @Override
    public int compareTo(Contact o) {
        return Integer.compare(this.id, o.id);
    }
}
javac -cp lib/lombok.jar  src/merge/Main.java -d out/
java -cp lib/lombok.jar:out  merge.Main
Result= [Contact(id=1, name=j, phone=123), Contact(id=3, name=k, phone=678)]