2012-07-01 3 views
1

내부 클래스 내부에 부울 플래그를 설정해야 할 때가 종종 자바 코드에 상황이 있습니다. 이 내부 클래스는 외부에서 최종 변수 일 수 있기 때문에, 그것을 위해 기본 부울 형식을 사용할 수 없습니다, 그래서 나는 다음과 같은 패턴을 사용 :내부 클래스의 부울 플래그에 대한 최종 변수가 아닌 최종 배열 패턴

// class from gnu.trove is not of big importance, just to have an example 
private final TIntIntHashMap team = new TIntIntHashMap(); 
// ....... code ............ 
final boolean[] flag = new boolean[]{false}; 
team.forEachValue(new TIntProcedure() { 
    @Override 
    public boolean execute(int score) { 
     if(score >= VICTORY_SCORE) { 
      flag[0] = true; 
     } 
     return true; // to continue iteration over hash map values 
    } 
}); 
// ....... code .............. 

마지막 배열의 패턴 대신이 아닌 최종 변수 작품 잘, 저에게 충분히 아름답게 보이지 않는 것을 제외하고는. 누군가가 Java에서 더 나은 패턴을 알고 있습니까?

+0

대신의 매우 일반적인'forEachValue'를 사용하여, 기존 방법을 사용하거나 더 나은 use-에 맞는 자신 만의 방법을 쓸 수 케이스. 물론'exists (Iterator it, Predicate p)'또는'count (Iterator it, Predicate p) '와 같이 매우 일반적인 것을 사용할 수 있습니다. 나는이 명령형 접근법 대신에 기능적 접근법이 훨씬 깨끗하다고 ​​생각합니다. –

+1

Java에서 FP 구문을 사용하려고 시도한 결과, 마침내 포기했습니다. 가독성, 정확성 또는 다른 바람직한 코드 기능을 촉진하지 않습니다. Java 8이 이제는 닫히기 때문에, 기다리지 않는 이유는 거의 없습니다. –

답변

3

이 패턴이 가장 좋은 경우가 있습니다.

내가 제안 할 수있는 유일한 개선점은 일치 항목을 발견했을 때 return false입니다.

+0

그것은 단지 예일 뿐이다. 나는 iteration 내에서 다른 일을하므로 imediately로 돌아갈 수 없다. – Nulldevice

3

모든 유형의 객체를 보유하는 일반 홀더 클래스를 갖는 방법은 어떻습니까? 귀하의 경우에는 Boolean 유형을 보유 할 수 있습니다. 같은 뭔가 :

class Holder<T> {   
    private T genericObj; 

    public Holder(T genericObj) { 
     this.genericObj = genericObj; 
    } 

    public T getGenericObj() { 
     return genericObj; 
    } 

    public void setGenericObj(T genericObj) { 
     this.genericObj = genericObj; 
    }  
} 

그리고로 사용 : 물론

public class Test { 
    public static void main(String[] args) throws Exception {   
     final Holder<Boolean> boolHolder = new Holder<Boolean>(Boolean.TRUE); 
     new Runnable() {    
      @Override 
      public void run() { 
       boolHolder.setGenericObj(Boolean.FALSE); 
      } 
     }; 
    } 
} 

,이 스레드에서 공유하는 가변 객체로 발생하는 일반적인 문제가있다하지만 당신은 아이디어를 얻을. 메모리 요구 사항이 엄격한 응용 프로그램의 경우 플러스. 이러한 메소드를 많이 호출 할 경우 최적화를 수행 할 때 교차 될 수 있습니다. 또한 AtomicReference을 사용하여 참조를 스왑/설정하면 여러 스레드에서 사용하도록 처리해야하지만 스레드간에 사용하는 것은 여전히 ​​약간의 의문이 남습니다.

1

하나의 문제는 TIntIntHashMap에 fold/reduce 메서드가 없으므로 foreach를 사용하여 시뮬레이트해야한다는 것입니다. reduce 메소드를 추가하여 TIntIntHashMap을 확장하는 클래스를 직접 작성할 수도 있습니다.

다른 해결책은 값을 갖기 위해 TIntProcedure를 확장하는 것입니다. 같은 : 당신이 foreach는이 클래스의 인스턴스를 전달할 수있는 그런

abstract class TIntProcedureWithValue<T> implements TIntProcedure { 
    private T accumulator; 
    public T getValue() {return accumulator;} 
} 

는, 외부 플래그 배열 대신 내부 축적을 설정 한 후 결과 값을 얻을.

0

어쩌면 그럴 수 있습니까? (구현 또는 확장 ... 난 불행하게도, TIntProcedure 무엇인지 모르는) : AtomicBoolean

class FlagResult implements TIntProcedure { 
     boolean flag = false; 
     @Override 
     public boolean execute(int score) { 
      flag = score >= VICTORY_SCORE; 
      return !flag; 
     } 
    }; 
    FlagResult result = new FlagResult(); 
    team.forEachValue(result); 
    boolean flag = result.flag; 
6

사용.

다음은이 문제에 대한 인기에 StackOverflow의 질문 : Why are only final variables accessible in anonymous class?

+1

미학 (간결함)까지, 최종 배열 관용구를 이길 수는 없다. 이 솔루션에는 더 많은 상용구가 있습니다. –

+0

java.util.concurrent.atomic의 오브젝트에 대한 문제점은 성능 비용이 있다는 것입니다. 동기화는 무료가 아니며 제 경우에는 필요하지 않습니다. – Nulldevice

+0

@nulldevice : 값 비싼 동기화는 [10 년 된 도시의 전설]입니다. (http://www.ibm.com/developerworks/java/library/j-jtp04223/index.html) ... JDK 1.3을 사용하지 않습니다. 더 이상. 기사에서 말하는 것처럼, 런타임은 불필요한 동기화를 감지 할 수도 있습니다. 즉, 이와 같은 간단한 경우에 최적화 될 가능성이 매우 높습니다. –

1

내가 gnu.trove에 익숙하지 않은,하지만 일반적으로는 여기에 적은 코드를 떠나, 더 구체적으로하려면 "algortihm"기능에 대한 좋습니다.

private final IntIntHashMap team = new IntIntHashMap(); 

boolean found = team.value().containsMatch(new IntPredicate() { 
    public boolean is(int score) { 
     return score >= VICTORY_SCORE; 
    } 
}); 

(더 간결한 구문은 자바 SE에서 사용할 수 8.한다)