2015-04-18 5 views
0

Я пытаюсь создать реализацию TransformList, которая поддерживает список различных значений из списка источников. Тем не менее, я немного озадачен тем, как реализация должна добавить отдельные значения в мой хэш-файл и отдельный список, которые содержатся внутри. Я думаю, что мой ListChangeListener.change должен работать. Но как я могу перехватить любые новые или удаленные отдельные значения и добавить/удалить их на отдельную карту и список?Реализовать TransformList, который содержит различные значения?

public class DistinctList<E> extends TransformationList<E,E> { 

    private final ObservableList<E> distinctList = FXCollections.observableArrayList(); 
    private final ConcurrentHashMap<E,E> distinctValues = new ConcurrentHashMap<>(); 
    private final ObservableList<E> source; 

    public DistinctList(ObservableList<E> source) { 
     super(source); 
     this.source = source; 
     source.stream().filter(s -> attemptAdd(s)).forEach(s -> distinctList.add(s)); 
    } 
    private boolean attemptAdd(E e) { 
     final boolean result = distinctValues.putIfAbsent(e,e) == null; 
     if (result) { 
      distinctList.add(e); 
     } 
     return result; 
    } 
    private boolean attemptRemove(E e) { 
     final boolean result = distinctValues.remove(e, e); 
     if (result) { 
      distinctList.remove(e); 
     } 
     return result; 
    } 

    @Override 
    protected void sourceChanged(ListChangeListener.Change<? extends E> c) { 
     fireChange(new ListChangeListener.Change<E>(this) { 

      @Override 
      public boolean wasAdded() { 
       if (c.getAddedSubList().stream().filter(v -> distinctValues.contains(v) == false).findAny().isPresent()) { 
        return true; 
       } 
       else { 
        return false; 
       } 
      } 

      @Override 
      public boolean wasRemoved() { 
       if (c.getRemoved().stream().filter(v -> !source.contains(v)).findAny().isPresent()) { 
        return true; 
       } 
       else { 
        return false; 
       } 
      } 

      @Override 
      public boolean wasPermutated() { 
       return false; 
      } 


      @Override 
      protected int[] getPermutation() { 
       throw new AssertionError("getPermutation() not implemented"); 
      } 

      @Override 
      public List<E> getRemoved() { 
       return c.getRemoved().stream().filter(v -> !source.contains(v)).collect(Collectors.toList()); 
      } 

      @Override 
      public int getFrom() { 
       return 0; 
      } 

      @Override 
      public int getTo() { 
       return 0; 
      } 

      @Override 
      public boolean next() { 
       return c.next(); 
      } 

      @Override 
      public void reset() { 
       c.reset(); 
      } 
     }); 
    } 

    @Override 
    public int getSourceIndex(int index) { 
     return IntStream.range(0,source.size()).filter(i -> source.get(i).equals(this.get(i))).findAny().orElse(-1); 
    } 

    @Override 
    public E get(int index) { 
     return distinctList.get(index); 
    } 

    @Override 
    public int size() { 
     return distinctList.size(); 
    } 
} 

UPDATE

Я продолжал работать с этим, и я думаю, что я понял, где взаимодействие изменения источника с отдельной картой значения и список. Но когда мой исходный список удаляет значение (и другие значения с одинаковым значением hashcode/equals все еще существуют), он ошибочно удаляет значение из различных значений. Что я делаю не так?

public class DistinctList<E> extends TransformationList<E,E> { 

    private final ObservableList<E> distinctList = FXCollections.observableArrayList(); 
    private final ConcurrentHashMap<E,E> distinctValues = new ConcurrentHashMap<>(); 
    private final ObservableList<E> source; 


    public DistinctList(ObservableList<E> source) { 
     super(source); 
     this.source = source; 
     source.stream().forEach(s -> attemptAdd(s)); 
    } 
    private boolean attemptAdd(E e) { 
     final boolean result = distinctValues.putIfAbsent(e,e) == null; 
     if (result) { 
      distinctList.add(e); 
     } 
     return result; 
    } 
    private boolean attemptRemove(E e) { 
     final boolean result = distinctValues.remove(e, e); 
     if (result) { 
      distinctList.remove(e); 
     } 
     return result; 
    } 

    @Override 
    protected void sourceChanged(ListChangeListener.Change<? extends E> c) { 
     ListChangeListener.Change<E> change = new ListChangeListener.Change<E>(this) { 
      @Override 
      public boolean wasAdded() { 
       if (c.getAddedSubList().stream().filter(v -> source.contains(v)).findAny().isPresent()) { 
        return true; 
       } 
       else { 
        return false; 
       } 
      } 

      @Override 
      public boolean wasRemoved() { 
       if (c.getRemoved().stream().filter(v -> source.contains(v) == false).findAny().isPresent()) { 
        return true; 
       } 
       else { 
        return false; 
       } 
      } 

      @Override 
      public boolean wasPermutated() { 
       return false; 
      } 


      @Override 
      protected int[] getPermutation() { 
       throw new AssertionError("getPermutation() not implemented"); 
      } 

      @Override 
      public List<E> getRemoved() { 
       return c.getRemoved().stream().filter(v -> source.contains(v) == false) 
         .collect(Collectors.toList()); 
      } 

      @Override 
      public int getFrom() { 
       return 0; 
      } 

      @Override 
      public int getTo() { 
       return 0; 
      } 

      @Override 
      public boolean next() { 
       return c.next(); 
      } 

      @Override 
      public void reset() { 
       c.reset(); 
      } 
     }; 

     while (c.next()) { 
      if (c.wasAdded()) { 
       c.getAddedSubList().stream().filter(v -> !distinctValues.containsKey(v)).peek(a -> System.out.println("ADDING FROM MAP " + a)).forEach(a -> attemptAdd(a)); 
      } 
      if (c.wasRemoved()) { 
       c.getRemoved().stream().filter(v -> distinctValues.containsKey(v)).peek(a -> System.out.println("REMOVING FROM MAP " + a)).forEach(a -> attemptRemove(a)); 
      } 
     } 

     fireChange(change); 
    } 

    @Override 
    public int getSourceIndex(int index) { 
     return IntStream.range(0,source.size()).filter(i -> source.get(i).equals(this.get(i))).findAny().orElse(-1); 
    } 

    @Override 
    public E get(int index) { 
     return distinctList.get(index); 
    } 

    @Override 
    public int size() { 
     return distinctList.size(); 
    } 
} 
+1

не совсем дубликат, но тесно связаны с ранее вопрос: http://stackoverflow.com/q/29656772/203657 – kleopatra

+0

В духе да это дубликат, хотя я это попытки довольно различный вектор выполнение. – tmn

ответ

0

Я думаю, что понял. Дайте мне знать, если я что-то упустил.

public class DistinctList<E> extends TransformationList<E,E> { 

    private final ObservableList<E> distinctList = FXCollections.observableArrayList(); 
    private final ConcurrentHashMap<E,E> distinctValues = new ConcurrentHashMap<>(); 
    private final ObservableList<E> source; 


    public DistinctList(ObservableList<E> source) { 
     super(source); 
     this.source = source; 
     source.stream().forEach(s -> attemptAdd(s)); 
    } 
    private boolean attemptAdd(E e) { 
     final boolean result = distinctValues.putIfAbsent(e,e) == null; 
     if (result) { 
      distinctList.add(e); 
     } 
     return result; 
    } 
    private boolean attemptRemove(E e) { 
     final boolean result = distinctValues.remove(e, e); 
     if (result) { 
      distinctList.remove(e); 
     } 
     return result; 
    } 

    @Override 
    protected void sourceChanged(ListChangeListener.Change<? extends E> c) { 

     while (c.next()) { 
      ListChangeListener.Change<E> change = new ListChangeListener.Change<E>(this) { 
       @Override 
       public boolean wasAdded() { 
        if (c.getAddedSubList().stream().filter(v -> distinctValues.contains(v) == false).findAny().isPresent()) { 
         return true; 
        } else { 
         return false; 
        } 
       } 

       @Override 
       public List<E> getAddedSubList() { 
       return c.getAddedSubList().stream().filter(v -> distinctValues.contains(v) == false).collect(Collectors.toList()); 
       } 

       @Override 
       public boolean wasRemoved() { 
        if (c.getRemoved().stream().filter(v -> source.contains(v) == false).findAny().isPresent()) { 
         return true; 
        } else { 
         return false; 
        } 
       } 

       @Override 
       public boolean wasPermutated() { 
        return false; 
       } 


       @Override 
       protected int[] getPermutation() { 
        throw new AssertionError("getPermutation() not implemented"); 
       } 

       @Override 
       public List<E> getRemoved() { 
        return c.getRemoved().stream().filter(v -> source.contains(v) == false) 
          .collect(Collectors.toList()); 
       } 

       @Override 
       public int getFrom() { 
        return 0; 
       } 

       @Override 
       public int getTo() { 
        return 0; 
       } 

       @Override 
       public boolean next() { 
        return c.next(); 
       } 

       @Override 
       public void reset() { 
        c.reset(); 
       } 
      }; 

      if (change.wasAdded()) { 
       change.getAddedSubList().stream().filter(v -> !distinctValues.containsKey(v)).peek(a -> System.out.println("ADDING FROM MAP " + a)).forEach(a -> attemptAdd(a)); 
      } 
      if (change.wasRemoved()) { 
       change.getRemoved().stream().filter(v -> distinctValues.containsKey(v)).peek(a -> System.out.println("REMOVING FROM MAP " + a)).forEach(a -> attemptRemove(a)); 
      } 
      fireChange(change); 
     } 

    } 

    @Override 
    public int getSourceIndex(int index) { 
     return IntStream.range(0,source.size()).filter(i -> source.get(i).equals(this.get(i))).findAny().orElse(-1); 
    } 

    @Override 
    public E get(int index) { 
     return distinctList.get(index); 
    } 

    @Override 
    public int size() { 
     return distinctList.size(); 
    } 
} 
+1

не заглядывал в детали, но: не управляйте самим изменением - вы, скорее всего, сделаете это неправильно, это не тривиально, команда сборщиков заняла годы, чтобы понять это правильно! - вместо этого используйте методы nextXX (XX = Replace/deleted/added и т. д.). – kleopatra

+0

Хорошо, посмотрим. Я думаю, что стоит узнать, как преобразовать списки, потому что сложные бизнес-задачи часто меняют данные. Но я, конечно, хочу использовать любые вспомогательные классы, а не идти на низкий уровень. – tmn

Смежные вопросы