Issue
is there a filtered view of a collection (a subset of it) in Java, so that adding new item to it can also affect the source collection?
e.g.
List<String> source = new ArrayList<>();
source.add("a");
source.add("b");
List<String> view = source.stream().filter(i -> "b".equals(i)).collect(...);
view.add("c"); // source now contains also "c"
Solution
JDK provides only index-based view of the list with the method List::subList
:
The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.
Thus, the changes to the view can be applied to the source list too if the "filter" is constructed using List::indexOf
and/or List::lastIndexOf
.
This should be enough for a limited case of having a single range matching the condition:
List<String> source = new ArrayList<>();
source.add("a");
source.add("b");
source.add("b");
List<String> view = source.subList(source.indexOf("b"), source.lastIndexOf("b") + 1);
System.out.println("view: " + view);
view.add("c");
System.out.println("added view: " + view);
System.out.println("fixed src: " + source);
Output:
view: [b, b]
added view: [b, b, c]
fixed src: [a, b, b, c]
As for the filtered view of a list which stores all the source's elements matching some condition, such view would have to maintain a collection of sublists/subranges in general case and implement List
interface appropriately.
The Guava Collections2.filter
mentioned by @Wilderness Ranger above may be an example of the filtered view, however, its documentation states that its methods add
/addAll
would throw IllegalArgumentException
if the predicate is not satisfied, so in your example an attempt to add "c" would fail for the predicate "b"::equals
.
Answered By - Nowhere Man
Answer Checked By - David Marino (JavaFixing Volunteer)