code: @Override
    public <K, S, T> KVStreamlet<KeyedWindow<K>, T>
          join(Streamlet<S> otherStreamlet, SerializableFunction<R, K> thisKeyExtractor,
               SerializableFunction<S, K> otherKeyExtractor, WindowConfig windowCfg,
               JoinType joinType, SerializableBiFunction<R, S, ? extends T> joinFunction) {
      checkNotNull(otherStreamlet, "otherStreamlet cannot be null");
      checkNotNull(thisKeyExtractor, "thisKeyExtractor cannot be null");
      checkNotNull(otherKeyExtractor, "otherKeyExtractor cannot be null");
      checkNotNull(windowCfg, "windowCfg cannot be null");
      checkNotNull(joinType, "joinType cannot be null");
      checkNotNull(joinFunction, "joinFunction cannot be null");
  
      StreamletImpl<S> joinee = (StreamletImpl<S>) otherStreamlet;
      JoinStreamlet<K, R, S, T> retval = JoinStreamlet.createJoinStreamlet(
          this, joinee, thisKeyExtractor, otherKeyExtractor, windowCfg, joinType, joinFunction);
      addChild(retval);
      joinee.addChild(retval);
      return new KVStreamletShadow<KeyedWindow<K>, T>(retval);
    }
docs: Return a new KVStreamlet by joining 'this streamlet with ‘other’ streamlet. The type of joining
  is declared by the joinType parameter.
  The join is done over elements accumulated over a time window defined by windowCfg.
  The elements are compared using the thisKeyExtractor for this streamlet with the
  otherKeyExtractor for the other streamlet. On each matching pair, the joinFunction is applied.
  Types of joins {@link JoinType}
  @param otherStreamlet The Streamlet that we are joining with.
  @param thisKeyExtractor The function applied to a tuple of this streamlet to get the key
  @param otherKeyExtractor The function applied to a tuple of the other streamlet to get the key
  @param windowCfg This is a specification of what kind of windowing strategy you like to
  have. Typical windowing strategies are sliding windows and tumbling windows
  @param joinType Type of Join. Options {@link JoinType}
  @param joinFunction The join function that needs to be applied