The purpose of this question is to give you practice writing some static methods that use one or more generic parameters, and that also use streams.
-
Immutable pair. Write a generic class,
ImmutablePair
, with two generic parameters,S
andT
say, that allows the construction of an (S
,T
) pair, and retrieval of its first and second components. OverridetoString()
so that a pair is represented as a string of the form(
string representation of first element,
string representation of second element)
. -
Placeholder class. Create a class,
Example
, to serve as a placeholder for the static methods you will write. -
Generic list concatenation Recall the
concatenate
function from question 68e6, which had the signature:static List<Integer> concatenate(List<List<Integer>> lists);
and returned the concatenation of the lists in
lists
. Observe that there is nothingInteger
-specific about the notion of concatenating lists.Write a version of
concatenate
that is generic with respect to some typeT
, and which takes a list of lists of typeList<List<T>>
, and returns aList<T>
that is the concatenation of these lists. -
Zip lists of different lengths Write a static method,
zip
, that is generic with respect to two parameters,S
andT
, and that takes two parameters, a listfirst
of typeList<S>
and a listsecond
of typeList<T>
. The method should return a list of typeList<ImmutablePair<Optional<S>, Optional<T>>>
. At each index i less than the minimum size offirst
andsecond
, the result should have a pair of present optionals corresponding to the elements at indices i offirst
andsecond
. At each index j (if any) at least the minimum size offirst
andsecond
and less than the maximum size offirst
andsecond
, the result should have a pair consisting of one present optional and one empty optional; the present optional should be the value at index j of the input list, which must exist.
The zip
function is not a good fit for using streams, so feel free to use a loop-based solution. If you are interested in playing more with streams, then consider using the IntStream.range()
method to get a stream of integers as long as the maximum size of the two lists, and then use mapToObj
to map each integer to the appropriate pair, by get
ting list elements when they are needed.
- Flattening pairs of optionals Write a static method,
flatten
, that is generic with respect to two types,S
andT
. Theflatten
method should take three parameters: a list,maybePairs
of typeList<ImmutablePair<Optional<S>, Optional<T>>>
, an elementdefaultS
of typeS
, and an elementdefaultT
of typeT
.flatten
should return a list of typeList<ImmutablePair<S, T>>
such that:
- if an element
s
of typeS
is present as the first component of the pair at index i ofmaybePairs
present, the first component of the pair at index i of the result list iss
, otherwise it isdefaultS
; - if an element
t
of typeT
is present as the first component of the pair at index i ofmaybePairs
present, the first component of the pair at index i of the result list ist
, otherwise it isdefaultT
.
The idea is that the method flattens a list of pairs of optionals into a list of pairs, using the given default values wherever an empty optional appears.
Try to write this method using streams, rather than loops.
- Writing a main method Add a
main
method toExample
that demonstrates your example methods in action on some example data.