1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Eachっていうクラス書いてみた

Last updated at Posted at 2013-02-03

javaでよく、

before
BigDecimal result= BigDecimal.ZERO;

for(BigDecimal elm : collection_of_BigDecimal){
    if(elm != null){
        result= result.add(elm);
    }
}

↑のようなコードを書くのだけど、なんかうまくないなぁと思ってた。
で、↓のようなクラス書いてみた。

jp.michikusa.chitose.util.math.Each
package jp.michikusa.chitose.util.math;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.Collection;
import java.util.List;

import com.google.common.collect.Lists;

public class Each<E, R>{
    public static interface Operator<E, R>{
        R apply(R a, E b);
    }
    
    public static <E, R>Each<E, R> of(Operator<? super E, R> op){
        return new Each<>(op, null);
    }
    
    public Each<E, R> skipNulls(){
        return new SkipNulls<>(this);
    }
    
    public Each<E, R> useForNull(E null_value){
        return new UseForNull<E, R>(this, null_value);
    }
    
    public final Each<E, R> startWith(R start_with){
        return this.newEach(this.op, start_with);
    }
    
    public final R applyTo(Collection<? extends E> elms){
        List<E> working= Lists.newArrayList(elms);
        
        R result= this.start_with;
        for(E elm : working){
            result= this.apply(result, elm);
        }
        
        return result;
    }
    
    protected R apply(R result, E elm){
        return this.op.apply(result, elm);
    }
    
    protected Each<E, R> newEach(Operator<? super E, R> op, R start_with){
        return new Each<>(op, start_with);
    }
    
    private static class UseForNull<E, R> extends Each<E, R>{
        public UseForNull(Each<? super E, R> prototype, E null_value){
            super(prototype.op, prototype.start_with);
            
            this.null_value= checkNotNull(null_value);
        }
        
        @Override
        public Each<E, R> useForNull(E null_value){
            throw new UnsupportedOperationException();
        }
        
        @Override
        public Each<E, R> skipNulls(){
            throw new UnsupportedOperationException();
        }
        
        @Override
        protected R apply(R result, E elm){
            return super.apply(result, this.get(elm));
        }
        
        @Override
        protected Each<E, R> newEach(Operator<? super E, R> op, R start_with){
            return new UseForNull<>(new Each<>(op, start_with), this.null_value);
        }
        
        private E get(E origin){
            if(origin == null){ return this.null_value; }
            
            return origin;
        }
        
        private final E null_value;
    }
    
    private static class SkipNulls<E, R> extends Each<E, R>{
        public SkipNulls(Each<E, R> prototype){
            super(prototype.op, prototype.start_with);
        }
        
        @Override
        public Each<E, R> skipNulls(){
            throw new UnsupportedOperationException();
        }
        
        @Override
        public Each<E, R> useForNull(E null_value){
            throw new UnsupportedOperationException();
        }
        
        @Override
        protected R apply(R result, E elm){
            if(elm == null){ return result; }
            
            return super.apply(result, elm);
        }
        
        @Override
        protected Each<E, R> newEach(Operator<? super E, R> op, R start_with){
            return new SkipNulls<>(this);
        }
    }
    
    private Each(Operator<? super E, R> op, R start_with){
        checkNotNull(op);
        
        this.op= op;
        this.start_with= start_with;
    }
    
    private final Operator<? super E, R> op;
    private final R                      start_with;
}

これで↓のように書ける。

after
List<Integer> elms= Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

Integer result= Each.of(new Operator<Integer, Integer>(){
    @Override
    public Integer apply(Integer a, Integer b){
        return a + b;
    }
}).startWith(0).applyTo(elms);

assertEquals(Integer.valueOf(36), result);

要素としてnullが入る可能性があるなら、こんな感じ。

nullable0
List<Integer> elms= Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

Integer result= Each.of(new Operator<Integer, Integer>(){
    @Override
    public Integer apply(Integer a, Integer b){
        return a + b;
    }
}).startWith(0).useForNull(0).applyTo(elms);

assertEquals(Integer.valueOf(36), result);
nullable1
List<Integer> elms= Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

Integer result= Each.of(new Operator<Integer, Integer>(){
    @Override
    public Integer apply(Integer a, Integer b){
        return a + b;
    }
}).startWith(0).skipNulls().applyTo(elms);

assertEquals(Integer.valueOf(36), result);

まだテストあんまりしてないから、バグあるかも。

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?