0

I have a model class:

public class Person{
    private String personnelId;
    private String lastName;
    private String firstName;
}

Now I have service class

public class A{
    @Autowired
    private OfficerService officer;

    public List<Person> getAccounts(Param param){
        List<Person> personList = personDao.getAccounts(param);
        List<String> stringList = personList.stream().map(Person::getPersonnelId).collect(Collectors.toList());
        List<String> list = Officer.getVisiblePerson(stringList);
        List<Person> visiblePersonList= new ArrayList<>();

        return visiblePersonList;
    }

Now when I convert List<Person> into List<String> which gets the personnelId from Model class. After the method call I get back personnelId. I need to convert back into List<Person> which will contain all the data with firstName and lastName in Person class attached to that Id. How can I do that?

EDIT:

Map<String, Person> personMap = personList.stream()
        .collect(Collectors.toMap(Person::getPersonnelId, person -> person));
    List<Person> visiblePersonList = list.stream()
        .map(id -> personMap.get(id))
        .collect(Collectors.toList());

I get an error on collect of map:

The method collect(Collector<? super String,A,R>) in the type Stream<String> is not applicable for the arguments (Collector<Person,capture#2-of ?,Map<String,Object>>)

What am i doing wrong?

6
  • Is the conversion to List<String> really necessary? Commented Aug 26, 2016 at 3:05
  • 3
    If you want it as a model why did you convert it to a string? Commented Aug 26, 2016 at 3:09
  • Yeah im consuming some 3rd party service and that service only takes string. Commented Aug 26, 2016 at 3:20
  • 2
    What does Officer.getVisiblePerson(...) do? Commented Aug 26, 2016 at 3:28
  • 'Officer.getVisiblePerson(...)' takes 'List<String>' of Ids, consumes 3rd party service and gives back 'List<String>' of Ids which are accessible to Officer in question from the Person Object. Is there a better way to do what I'm doing? Commented Aug 26, 2016 at 3:37

2 Answers 2

2

One way to will be to have it in a map and then get these values from a map. There is one additional iteration , but depending on how big the list is or if it can be parallel , performance will be slightly more or less.

public static void main(String[] args) throws Exception {
    List<Person> personList = new ArrayList<Person>(); // personDao.getAccounts(param);

    Person person1 = new Person("1", "ln1", "fn1");
    Person person2 = new Person("2", "ln2", "fn2");
    Person person3 = new Person("3", "ln3", "fn3");
    Person person4 = new Person("4", "ln4", "fn4");
    personList.add(person1);
    personList.add(person2);
    personList.add(person3);
    personList.add(person4);

/*Of interest , the logic*/
        List<String> stringList = personList.stream().map(Person::getPersonnelId).collect(Collectors.toList());
        Map<String, Person> mapStringToPerson = personList.stream()
                .collect(Collectors.toMap(Person::getPersonnelId, person -> person));

/*as a logic filter even number id , in a real life this will be officer filter*/
            List<String> listFiltered = stringList.stream().filter(personId -> (Integer.parseInt(personId) % 2 == 0))
                    .collect(Collectors.toList());// Officer.getVisiblePerson(stringList);
            List<Person> visiblePersonList = listFiltered.stream().filter(id -> mapStringToPerson.containsKey(id))
                    .map(id -> mapStringToPerson.get(id)).collect(Collectors.toList());
            visiblePersonList.forEach(System.out::println);

}

Prints ::

    Person with id : 2 and name fn2 ln2
    Person with id : 4 and name fn4 ln4
Sign up to request clarification or add additional context in comments.

Comments

1

First, let me address some naming issues:

  • Officer should be officer.

  • stringList should be named idList, since that's what it contains, conceptually. You don't name it for the type, because:

    1. You can see that by looking at ... (you guessed it) ... the type.
    2. Saying "String" is meaningless and says nothing about what the string represents.
  • Similarly, list should be named visibleIdList.

Now I'll use the name I just suggested.

Since getVisiblePerson() returns a list of the entries from idList that are visible, i.e. a filtered list, you can do one of two things:

  1. Create Map<String, Person> of id to Person, then iterate visibleIdList and lookup the Person and build a list of that.

  2. Turn visibleIdList into a visibleIdSet, then iterate personList and filter to those in the Set.

Option 2 has a smaller memory footprint, and likely better performance too.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.