What is equivalent to C#'s Select clause in JAVA's streams API

前端 未结 4 1582
误落风尘
误落风尘 2020-12-31 21:38

I wanted to filter list of Person class and finally map to some anonymous class in Java using Streams. I am able to do the same thing very easily in C#.

Person class

相关标签:
4条回答
  • 2020-12-31 21:58

    If you know which attributes to select and this does not change, I would recommend writing a small class with that subset of Person's attributes. You can then map every person to an instance of that class and collect them into a list:

    Stream.of(new Person(1, "a", "aa"), new Person(2, "b", "bb"), new Person(3, "b", "bbb"),
              new Person(4, "c", "aa"), new Person(5, "b", "bbb"))
          .filter(person -> true)    // your filter criteria goes here
          .map(person -> new PersonSelect(person.getName(), person.getAddress()))
          .collect(Collectors.toList());
    
    // result in list of PersonSelects with your name and address
    

    If the set of desired attributes varies, you could use an array instead. It will look more similar to your C# code, but does not provide type safety:

    Stream.of(new Person(1, "a", "aa"), new Person(2, "b", "bb"), new Person(3, "b", "bbb"),
              new Person(4, "c", "aa"), new Person(5, "b", "bbb"))
          .filter(person -> true)
          .map(person -> new Object[] {person.getName(), person.getAddress()})
          .collect(Collectors.toList())
          .forEach(p -> System.out.println(Arrays.asList(p)));
    
    // output: [a, aa], [b, bb], [b, bbb], [c, aa], [b, bbb]
    
    0 讨论(0)
  • 2020-12-31 22:10

    It seems that you want to transform your Person with 3 properties to a Holder that has 2 properties. And that is a simple map operation:

    lst.stream().map(p -> new AbstractMap.SimpleEntry(p.address, p.name))
                              .collect(Collectors.toList());
    

    This is collecting your entries to SimpleEntry that is just a Holder for two values. If you need more then two, you are out of luck - you will need to create your own holder(class).

    0 讨论(0)
  • 2020-12-31 22:11

    Well, you can map Person instances to instances of anonymous classes, e.g. assuming

    class Person {
        int id;
        String name, address;
    
        public Person(String name, String address, int id) {
            this.id = id;
            this.name = name;
            this.address = address;
        }
        public int getId() {
            return id;
        }
        public String getName() {
            return name;
        }
        public String getAddress() {
            return address;
        }
    }
    

    you can do

    List<Person> lst = Arrays.asList(
                           new Person("Pava", "India", 1), new Person("tiwari", "USA", 2));
    List<?> result = lst.stream()
        .map(p -> new Object() { String address = p.getAddress(); String name = p.getName(); })
        .collect(Collectors.toList());
    

    but as you might note, it’s not as concise, and, more important, the declaration of the result variable can’t refer to the anonymous type, which makes the instances of the anonymous type almost unusable.

    Currently, lambda expressions are the only Java feature that supports declaring variables of an implied type, which could be anonymous. E.g., the following would work:

    List<String> result = lst.stream()
        .map(p -> new Object() { String address = p.getAddress(); String name = p.getName(); })
        .filter(anon -> anon.name.startsWith("ti"))
        .map(anon -> anon.address)
        .collect(Collectors.toList());
    
    0 讨论(0)
  • 2020-12-31 22:14

    If you want to create a list of new Person instances you first should provide a constructor, e.g. like this:

    class Person {
      public int id;
      public String name;
      public String address;
    
      public Person( int pId, String pName, String pAddress ) {
        super();
        id = pId;
        name = pName;
        address = pAddress;
      }
    }
    

    Then you could use the stream:

    List<Person> lst = new ArrayList<>();
    
    lst.add(new Person(1, "Pava", "India" ));
    lst.add(new Person( 2, "tiwari", "USA" ) );
    
    //since id is an int we can't use null and thus I used -1 here    
    List<Person> result = lst.stream().map(p -> new Person(-1, p.name, p.address)).collect(Collectors.toList());
    

    If you want to filter persons then just put a filter() in between stream() and map():

    List<Person> result = lst.stream().filter(p -> p.name.startsWith( "P" )).map(p -> new Person( -1, p.name, p.address )).collect(Collectors.toList());
    
    0 讨论(0)
提交回复
热议问题