Java 8 lambda get and remove element from list

后端 未结 12 1553
说谎
说谎 2020-12-08 12:47

Given a list of elements, I want to get the element with a given property and remove it from the list. The best solution I found is:

Produce         


        
相关标签:
12条回答
  • 2020-12-08 13:04

    As others have suggested, this might be a use case for loops and iterables. In my opinion, this is the simplest approach. If you want to modify the list in-place, it cannot be considered "real" functional programming anyway. But you could use Collectors.partitioningBy() in order to get a new list with elements which satisfy your condition, and a new list of those which don't. Of course with this approach, if you have multiple elements satisfying the condition, all of those will be in that list and not only the first.

    0 讨论(0)
  • 2020-12-08 13:07

    With Eclipse Collections you can use detectIndex along with remove(int) on any java.util.List.

    List<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
    int index = Iterate.detectIndex(integers, i -> i > 2);
    if (index > -1) {
        integers.remove(index);
    }
    
    Assert.assertEquals(Lists.mutable.with(1, 2, 4, 5), integers);
    

    If you use the MutableList type from Eclipse Collections, you can call the detectIndex method directly on the list.

    MutableList<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
    int index = integers.detectIndex(i -> i > 2);
    if (index > -1) {
        integers.remove(index);
    }
    
    Assert.assertEquals(Lists.mutable.with(1, 2, 4, 5), integers);
    

    Note: I am a committer for Eclipse Collections

    0 讨论(0)
  • 2020-12-08 13:08

    the task is: get ✶and✶ remove element from list

    p.stream().collect( Collectors.collectingAndThen( Collector.of(
        ArrayDeque::new,
        (a, producer) -> {
          if( producer.getPod().equals( pod ) )
            a.addLast( producer );
        },
        (a1, a2) -> {
          return( a1 );
        },
        rslt -> rslt.pollFirst()
      ),
      (e) -> {
        if( e != null )
          p.remove( e );  // remove
        return( e );    // get
      } ) );
    
    0 讨论(0)
  • 2020-12-08 13:10

    Use can use filter of Java 8, and create another list if you don't want to change the old list:

    List<ProducerDTO> result = producersProcedureActive
                                .stream()
                                .filter(producer -> producer.getPod().equals(pod))
                                .collect(Collectors.toList());
    
    0 讨论(0)
  • 2020-12-08 13:10

    Combining my initial idea and your answers I reached what seems to be the solution to my own question:

    public ProducerDTO findAndRemove(String pod) {
        ProducerDTO p = null;
        try {
            p = IntStream.range(0, producersProcedureActive.size())
                 .filter(i -> producersProcedureActive.get(i).getPod().equals(pod))
                 .boxed()
                 .findFirst()
                 .map(i -> producersProcedureActive.remove((int)i))
                 .get();
            logger.debug(p);
        } catch (NoSuchElementException e) {
            logger.error("No producer found with POD [" + pod + "]");
        }
        return p;
    }
    

    It lets remove the object using remove(int) that do not traverse again the list (as suggested by @Tunaki) and it lets return the removed object to the function caller.

    I read your answers that suggest me to choose safe methods like ifPresent instead of get but I do not find a way to use them in this scenario.

    Are there any important drawback in this kind of solution?

    Edit following @Holger advice

    This should be the function I needed

    public ProducerDTO findAndRemove(String pod) {
        return IntStream.range(0, producersProcedureActive.size())
                .filter(i -> producersProcedureActive.get(i).getPod().equals(pod))      
                .boxed()                                                                
                .findFirst()
                .map(i -> producersProcedureActive.remove((int)i))
                .orElseGet(() -> {
                    logger.error("No producer found with POD [" + pod + "]"); 
                    return null; 
                });
    }
    
    0 讨论(0)
  • 2020-12-08 13:11

    I'm sure this will be an unpopular answer, but it works...

    ProducerDTO[] p = new ProducerDTO[1];
    producersProcedureActive
                .stream()
                .filter(producer -> producer.getPod().equals(pod))
                .findFirst()
                .ifPresent(producer -> {producersProcedureActive.remove(producer); p[0] = producer;}
    

    p[0] will either hold the found element or be null.

    The "trick" here is circumventing the "effectively final" problem by using an array reference that is effectively final, but setting its first element.

    0 讨论(0)
提交回复
热议问题