While some people might loathe "optional methods", they may in many cases offer better semantics than highly-segregated interfaces. Among other things, they allow for the possibilities that an object might gain abilities or characteristics in its lifetime, or that an object (especially a wrapper object) might not know when it is constructed what exact abilities it should report.
While I will hardly call the Java collection classes paragons of good design, I would suggest that a good collections framework should include at its foundation a large number of optional methods along with ways of asking a collection about its characteristics and abilities. Such a design will allow a single wrapper class to be used with a large variety of collections without accidentally obscuring abilities the underlying collection might possess. If methods weren't optional, then it would be necessary to have a different wrapper class for every combination of features that collections might support, or else have some wrappers be unusable in some situations.
For example, if a collection supports writing an item by index, or appending items at the end, but does not support inserting items in the middle, then code wanting to encapsulate it in wrapper which would log all actions performed on it would need a version of the logging wrapper which provided for the exact combination of supported abilities, or if none was available would have to use a wrapper which supported either append or write-by-index but not both. If, however, a unified collection interface provided all three methods as "optional", but then included methods to indicate which of the optional methods would be usable, then a single wrapper class could handle collections which implement any combination of features. When asked what features it supports, a wrapper could simply report whatever the encapsulated collection supports.
Note that the existence of "optional abilities" may in some cases allow aggregated collections to implement certain functions in ways that were much more efficient than would be possible if abilities were defined by the existence of implementations. For example, suppose a
concatenate method was used to form a composite collection out of two others, the first of which happened to be an ArrayList with 1,000,000 elements and the last of which was a twenty-element collection which could only be iterated from the start. If the composite collection were asked for the 1,000,013th element (index 1,000,012), it could ask the ArrayList how many items it contained (i.e. 1,000,000), subtract that from the requested index (yielding 12), read and skip twelve elements from the second collection, and then return the next element.
In such a situation, even though the composite collection would not have an instantaneous way of returning an item by index, asking the composite collection for the 1,000,013th item would still be much faster than reading 1,000,013 items from it individually and ignoring all but the last one.