0

I have a List of Object. The Object is of type of Class - UserType.

public class UserType {

    private int userId = 0;
    private int userTypeId = 0;
    private String userType;

//Getters and Setters;

}

For the above mention List, I want to filter out the List based on the userType. The userType is not unique(can have same names and not duplicate), but a combination of userId, userTypeId and userType is unique.

So the requirement is, if I have userType as let us say - "ASSEMBLE", then I need to form a List with unique userType alone and also appending the userId and userTypeId as a List in the Bean.

EX: INPUT FORMAT:

[{userId: 1, userTypeId: 101, userType: "ASSEMBLE" },
{userId: 1, userTypeId: 102, userType: "ASSEMBLE" },
{userId: 2, userTypeId: 103, userType: "ARCHS" },
{userId: 3, userTypeId: 103, userType: "ARCHS" },
{userId: 4, userTypeId: 104, userType: "BAYLEAF" },
{userId: 4, userTypeId: 105, userType: "BAYLEAF" },
{userId: 5, userTypeId: 106, userType: "CHARSET" }]

EXPECTED: Results Filter out based on userType:

 [{userIds: [1] userTypeIds: [101,102], userType: "ASSEMBLE" },
    {userId: [2,3], userTypeId: [103], userType: "ARCHS" },
    {userId: [4], userTypeId: [104,105] userType: "BAYLEAF" },
    {userId: [5], userTypeId: [106], userType: "CHARSET" }]

So typically this must form a bean like -

public class UserType {

    private String userType;
    private List userIds = 0;
    private List userTypeIds = 0;


//Getters and Setters;

}

How to filter this object based on the requirement? Can also provide solutions in Javascript so that will look into one which is much optimized solutions. Thanks in advance.

5
  • 1
    Please edit your question: include some sample input and the expected output. Commented Mar 8, 2019 at 11:53
  • Maybe this question can help you? stackoverflow.com/q/41277862/6671476 Commented Mar 8, 2019 at 11:57
  • I have added the sample Input and Output @LutzHorn .. Commented Mar 8, 2019 at 12:12
  • There's a problem with your requirements. Take for example [{userId: 1, userTypeId: 101, userType: "ASSEMBLE" }, {userId: 2, userTypeId: 102, userType: "ASSEMBLE" }]. This gives [{userIds: [1,2] userTypeIds: [101,102], userType: "ASSEMBLE" }]. How do you distinguish that from an alternative input of [{userId: 1, userTypeId: 102, userType: "ASSEMBLE" }, {userId: 2, userTypeId: 101, userType: "ASSEMBLE" }]? Commented Mar 8, 2019 at 14:05
  • Yes, I can understand. Whatever the userId/userTypeId, we are going to filter it based on the userType which is going to be unique. Commented Mar 8, 2019 at 14:11

3 Answers 3

1

You can do this using a for loop and a Map like this:

import java.util.*;

public class GroupBy {

  public static void main(String[] args) {
    List<UserType> userTypes = new ArrayList<>();
    userTypes.add(new UserType(1, 101, "ASSEMBLE"));
    userTypes.add(new UserType(1, 102, "ASSEMBLE"));
    userTypes.add(new UserType(2, 103, "ARCHS"));
    userTypes.add(new UserType(3, 103, "ARCHS"));
    userTypes.add(new UserType(4, 104, "BAYLEAF"));
    userTypes.add(new UserType(4, 105, "BAYLEAF"));
    userTypes.add(new UserType(5, 106, "CHARSET"));

    Map<String, UserTypeGroup> map = new HashMap<>();
    for (UserType u : userTypes) {
      if (!map.containsKey(u.getUserType())) {
        map.put(u.getUserType(), new UserTypeGroup(u.getUserType()));
      }
      map.get(u.getUserType()).getUserIds().add(u.getUserId());
      map.get(u.getUserType()).getUserTypeIds().add(u.getUserTypeId());
    }

    System.out.println("INPUT:");
    System.out.println(userTypes);

    System.out.println("\nOUTPUT:");
    System.out.println(map.values());
  }
}

class UserType {

  private int userId;
  private int userTypeId;
  private String userType;

  UserType(int userId, int userTypeId, String userType) {
    this.userId = userId;
    this.userTypeId = userTypeId;
    this.userType = userType;
  }

  int getUserId() {
    return userId;
  }

  int getUserTypeId() {
    return userTypeId;
  }

  String getUserType() {
    return userType;
  }

  @Override
  public String toString()
  {
    return "{userId: " + userId + ", userTypeId: " + userTypeId +", userType: " + userType + "}\n";
  }
}

class UserTypeGroup {

  private String userType;
  private Set<Integer> userIds = new HashSet<>();
  private Set<Integer> userTypeIds = new HashSet<>();

  UserTypeGroup(String userType) {
    this.userType = userType;
  }

  Set<Integer> getUserIds() {
    return userIds;
  }

  Set<Integer> getUserTypeIds() {
    return userTypeIds;
  }

  @Override
  public String toString()
  {
    return "{userIds: " + userIds + ", userTypeIds: " + userTypeIds + ", userType: " + userType + "}\n";
  }
}

Output will be this:

INPUT:
[{userId: 1, userTypeId: 101, userType: ASSEMBLE}
, {userId: 1, userTypeId: 102, userType: ASSEMBLE}
, {userId: 2, userTypeId: 103, userType: ARCHS}
, {userId: 3, userTypeId: 103, userType: ARCHS}
, {userId: 4, userTypeId: 104, userType: BAYLEAF}
, {userId: 4, userTypeId: 105, userType: BAYLEAF}
, {userId: 5, userTypeId: 106, userType: CHARSET}
]

OUTPUT:
[{userIds: [5], userTypeIds: [106], userType: CHARSET}
, {userIds: [1], userTypeIds: [101, 102], userType: ASSEMBLE}
, {userIds: [2, 3], userTypeIds: [103], userType: ARCHS}
, {userIds: [4], userTypeIds: [104, 105], userType: BAYLEAF}
]
Sign up to request clarification or add additional context in comments.

4 Comments

That was a good solution, but still...Is there any way to do this with Java Streams? Also, I want the output in the form of List and Not as a Map.
Actually the output is a Collection; not a Map. Output is what is returned from map.values(). We can do this using steams. But it is ugly. No one likes ugly code. :)
(y) That served the purpose. but still would like to know how to do with stream. Can you please guide me ?
@AshfaqueRifaye, try something like this Map<String, Set<Integer>> userTypeToUserIdsMap = userTypes.stream().collect(Collectors.groupingBy(UserType::getUserType, Collectors.mapping(UserType::getUserId, Collectors.toSet())));. You have to do a similar thing to get userTypeIds map.
1

You can use an enhanced for loop to iterate over the objects in your List of objects. Call the getter method for the userType and check if it's equal to the word you want to filter. If so, add it's userId and userTypeId to the relevant Lists using getter methods.

EDIT : So after reading the comment, I have made changes and used a Set to get all the unique types and then made a list of UserList objects.

Like so:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Users{

    private List<UserType> objectList = new ArrayList<>();  //arraylist containing your objects
    private List<UserList> uniqueUserList = new ArrayList<>();

    private void filter() {   
        List<String> userTypeList = new ArrayList<>();
        for(UserType obj: objectList){
            userTypeList.add(obj.getType());    //get only Types
        }
        Set<String> uniqueUserTypes = new HashSet(userTypeList);    //set only contians unique strings
        for(String s: uniqueUserTypes)
        {
            addToUniqueList(s);
        }
    }

    private void addToUniqueList(String userTypeName){
        String filterBy = userTypeName;

        UserList listsForUniqueType = new UserList();
        listsForUniqueType.setType(filterBy);

        for(UserType obj: objectList) {
           if(obj.getType().equals(filterBy)){
               listsForUniqueType.addToUserId(obj.getId());
               listsForUniqueType.addToUserId(obj.getTypeId());
           }
        }
        uniqueUserList.add(listsForUniqueType);
    }

    public class UserList {
        private String userType;
        private List<Integer> userIds = new ArrayList<>();
        private List<Integer> userTypeIds = new ArrayList<>();

        public void setType(String typeName){
            userType = typeName;
        }
        public void addToUserId(int id){
            userIds.add(id);
        }
        public void addToTypeId(int id){
            userTypeIds.add(id);
        }
    }

    public class UserType {
        private int userId = 0;
        private int userTypeId = 0;
        private String userType;
        //Getters and Setters;
    }
}

2 Comments

The Problem is we don't have a filterBy criteria here. We need to filter it out from the List itself with the userType. @Vandan Adhvaryu
I have edited the answer for what you wanted, you can print out the contents of uniqueUserList to get your desired output (using getters in UserList).
1

Here's the solution using Java 8 streams:

import java.util.*;
import java.util.stream.Collector;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.groupingBy;

class UserType {

    private final int userId;
    private final int userTypeId;
    private final String userType;

    public UserType(int userId, int userTypeId, String userType) {
        this.userId = userId;
        this.userTypeId = userTypeId;
        this.userType = userType;
    }

    public int getUserId()      { return userId; }
    public int getUserTypeId()  { return userTypeId; }
    public String getUserType() { return userType; }

    @Override
    public String toString() {
        return "{userId: " + userId + ", userTypeId: " + userTypeId + ", userType: \"" + userType + "\"}";
    }
}

class UserTypeGroup {

    private final Set<Integer> userIds = new HashSet<>();
    private final Set<Integer> userTypeIds = new HashSet<>();
    private String userType;

    public UserTypeGroup add(UserType ut) {
        userIds.add(ut.getUserId());
        userTypeIds.add(ut.getUserTypeId());
        if (userType == null)
                userType = ut.getUserType();
        else if (!userType.equals(ut.getUserType()))
            throw new IllegalArgumentException("usertypes do not match");
        return this;
    }

    public UserTypeGroup combine(UserTypeGroup other) {
        userIds.addAll(other.userIds);
        userTypeIds.addAll(other.userTypeIds);
        if (userType == null)
            userType = other.userType;
        else if (!userType.equals(other.userType))
            throw new IllegalArgumentException("usertypes do not match");
        return this;
    }

    public Set<Integer> getUserIds()     { return Collections.unmodifiableSet(userIds); }
    public Set<Integer> getUserTypeIds() { return Collections.unmodifiableSet(userTypeIds); }
    public String getUserType()          { return userType; }

    @Override
    public String toString() {
        return "{userIds: " + userIds+ ", userTypeIds: " + userTypeIds + ", userType: \"" + userType + "\"}";
    }
}

class Main {
    public static void main(String[] args) {
        List<UserType> userTypes = Arrays.asList(
                new UserType(1, 101, "ASSEMBLE"),
                new UserType(1, 102, "ASSEMBLE"),
                new UserType(2, 103, "ARCHS"),
                new UserType(3, 103, "ARCHS"),
                new UserType(4, 104, "BAYLEAF"),
                new UserType(4, 105, "BAYLEAF"),
                new UserType(5, 106, "CHARSET"));
        Collection<UserTypeGroup> result = userTypes.stream()
                .collect(collectingAndThen(
                        groupingBy(
                                UserType::getUserType,
                                Collector.of(UserTypeGroup::new, UserTypeGroup::add, UserTypeGroup::combine)), 
                        Map::values));
        System.out.println(result);
    }
}

Output (with some newlines inserted manually for clarity):

[
    {userIds: [5], userTypeIds: [106], userType: "CHARSET"},
    {userIds: [1], userTypeIds: [101, 102], userType: "ASSEMBLE"},
    {userIds: [2, 3], userTypeIds: [103], userType: "ARCHS"},
    {userIds: [4], userTypeIds: [104, 105], userType: "BAYLEAF"}
]

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.