Okay, question is not so simple as it seems from the title.
Let's start from the beginning. Assume there are two collections containing DataRow objects:
public class DataRow<K, V> {
K key;
V value;
public DataRow(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
Example in pseudocode as follows:
c1 = [DataRow(0, "Italy"), DataRow(1, "Germany"), DataRow(2, "France")]
c2 = [DataRow(0, "Rome"), DataRow(1, "Berlin"), DataRow(3, "Budapest")]
It is needed to have 3 different ways of joining these collections in the one collection of JoinedDataRow's (Inner join, Left join, Right join):
public class JoinedDataRow<K, V1, V2> {
K key;
V1 value1;
V2 value2;
public JoinedDataRow(K key, V1 value1, V2 value2) {
this.key = key;
this.value1 = value1;
this.value2 = value2;
}
public K getKey() {
return key;
}
public V1 getValue1() {
return value1;
}
public V2 getValue2() {
return value2;
}
}
Operations are similar to the ones in SQL language.
Example of result for inner join: [JoinedDataRow(0, "Italy", "Rome"), JoinedDataRow(1, "Germany", "Berlin")]
There is an interface for these implementations of operations called JoinOperation:
public interface JoinOperation<D1, D2, R> {
Collection<R> join(Collection<D1> leftCollection, Collection<D2> rightCollection);
}
Where D1 and D2 are DataRow's and R is a JoinedDataRow (result)
And there are 3 implementations of the interface: InnerJoin, LeftJoin, RightJoin
There is no need to provide code for all three implementations. Here is just a skeleton for InnerJoin:
public class InnerJoinOperation<D1, D2, R> implements JoinOperation<D1, D2, R> {
@Override
public Collection<R> join(Collection<D1> leftCollection, Collection<D2> rightCollection) {
return null;
}
}
The problem: Right now it is possible and completely legal to pass to join method collection of Integers, for example.
join() method should look like this to avoid it:
@Override
public Collection<JoinedDataRow<K, V1, V2>> join(Collection<DataRow<K, V1>> leftCollection, Collection<DataRow<K, V2>> rightCollection) {
return null;
}
But it is forbidden to modify the interface JoinOperation, therefore the method above is not valid.
The question: How to restrict type of passed parameters in join method so that it would not be possible to pass anything except DataRow there.
I tried:
public class InnerJoinOperation<D1 extends DataRow, D2 extends DataRow, R extends JoinedDataRow> implements JoinOperation<D1, D2, R> {
@Override
public Collection<R> join(Collection<D1> leftCollection, Collection<D2> rightCollection) {
return null;
}
}
But here I am using raw DataRow and when I wanna do something like this:
Collection<DataRow<Integer, String>> lCollection = new ArrayList<>(List.of(
new DataRow<>(0, "Italy"),
new DataRow<>(1, "Germany"),
new DataRow<>(2, "France")
));
Collection<DataRow<Integer, String>> rCollection = new LinkedList<>(List.of(
new DataRow<>(0, "Rome"),
new DataRow<>(1, "Berlin"),
new DataRow<>(3, "Budapest")
));
var joiner = new InnerJoinOperation<>();
var joined = joiner.join(lCollection, rCollection);
expression joiner.join(lCollection, rCollection)
show compile time error:
enter image description here
CodePudding user response:
It sounds like what you want is just
public class InnerJoinOperation<K, V1, V2>
implements JoinOperation<DataRow<K, V1>, DataRow<K, V2>, JoinedDataRow<K, V1, V2>> {
@Override
public Collection<JoinedDataRow<K, V1, V2>> join(Collection<DataRow<K, V1>> leftCollection, Collection<DataRow<K, V2>> rightCollection) {
return null;
}
}