min和minby
min(“温度”),其他字段会是第一条数据的内容,一直带下去,只有温度值会被替换
minby("温度"),都会换成最小值的数据
示例论证
先拿min()与minBy()举例:
取第三个元素的最小值
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//获取数据源
List data = new ArrayList<Tuple3<Integer,Integer,Integer>>();
data.add(new Tuple3<>(0,2,2));
data.add(new Tuple3<>(0,1,1));
data.add(new Tuple3<>(0,5,6));
data.add(new Tuple3<>(0,3,5));
data.add(new Tuple3<>(1,1,9));
data.add(new Tuple3<>(1,2,8));
data.add(new Tuple3<>(1,3,10));
data.add(new Tuple3<>(1,2,9));
DataStreamSource<Tuple3<Integer,Integer,Integer>> items = env.fromCollection(data);
items.keyBy(0).min(2).print();
env.execute("defined streaming source");
}
输出结果:
(0,2,2)
(0,2,1)
(0,2,1)
(0,2,1)
(1,1,9)
(1,1,8)
(1,1,8)
(1,1,8)
可以看到返回的元素第二个字段取的是获取到第一个元素的字段值; 往下找,第二个元素的指定值是最小的,则把这个值保存的对应位置。
接下来再看minBy()的运行结果:
(0,2,2)
(0,1,1)
(0,1,1)
(0,1,1)
(1,1,9)
(1,2,8)
(1,2,8)
(1,2,8)
返回的是指定字段最小值的元素。可以看到元素数值的正确。
当然max(),maxBy同理。
reduce
对分组数据进行处理更为通用的方法是使用reduce
算子。
上图展示了reduce
算子的原理:reduce
在按照同一个Key分组的数据流上生效,它接受两个输入,生成一个输出,即两两合一地进行汇总操作,生成一个同类型的新元素。
case class Score(name: String, course: String, score: Int) val dataStream: DataStream[Score] = senv.fromElements( Score("Li", "English", 90), Score("Wang", "English", 88), Score("Li", "Math", 85), Score("Wang", "Math", 92), Score("Liu", "Math", 91), Score("Liu", "English", 87)) class MyReduceFunction() extends ReduceFunction[Score] { // reduce 接受两个输入,生成一个同类型的新的输出 override def reduce(s1: Score, s2: Score): Score = { Score(s1.name, "Sum", s1.score + s2.score) } } val sumReduceFunctionStream = dataStream .keyBy("name") .reduce(new MyReduceFunction)
使用Lambda表达式更简洁一些:
val sumLambdaStream = dataStream .keyBy("name") .reduce((s1, s2) => Score(s1.name, "Sum", s1.score + s2.score))
Split
根据某些特征把一个 DataStream 拆分成两个或者 多个 DataStream
示例如下:
功能描述:将传感器温度数据分成低温、高温(以 30 度为界)两条流
SplitStream<SensorReading> splitString = stream1.split(new OutputSelector<SensorReading>() {
@Override
public Iterable<String> select(SensorReading sensorReading) {
ArrayList<String> output = new ArrayList<String>();
if( sensorReading.temperature > 30.0 ){
output.add("high");
//sensorReading.lowOrhigt = "high";
}else{
output.add("low");
//sensorReading.lowOrhigt = "low";
}
return output;
}
});
Select
从一个 SplitStream 中获取一个或者多个 DataStream
示例如下:
功能描述:分别查询低温、高温(以 30 度为界)的数据
DataStream<SensorReading> highTempStream = splitString.select("high");
DataStream<SensorReading> lowTempStream = splitString.select("low");
Union
union用来合并两个或者多个流的数据,统一到一个流中
示例如下:
功能描述:分别低温、高温(以 30 度为界)的数据,合并成一个流
DataStream<SensorReading> resultUnion = highTempStream.union(lowTempStream,allTempStream);