//组合当前节点的标志和上一个节点的标志生成新的标志 //第一个参数10 //第二个参数95 staticintcombineOpFlags(int newStreamOrOpFlags, int prevCombOpFlags) { // 0x01 or 0x10 nibbles are transformed to 0x11 // 0x00 nibbles remain unchanged // Then all the bits are flipped // Then the result is logically or'ed with the operation flags. // 95 & -16 | 10 = 90 return (prevCombOpFlags & StreamOpFlag.getMask(newStreamOrOpFlags)) | newStreamOrOpFlags; }
@Override final StreamShape getOutputShape() { return StreamShape.REFERENCE; }
@Override publicfinal <R> Stream<R> flatMap(Function<? super P_OUT, ? extends Stream<? extends R>> mapper) { //参数校验 Objects.requireNonNull(mapper); // We can do better than this, by polling cancellationRequested when stream is infinite // 创建无状态节点并返回 returnnewStatelessOp<P_OUT, R>(this, StreamShape.REFERENCE, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) { @Override Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) { returnnewSink.ChainedReference<P_OUT, R>(sink) { @Override // 初始化数据 publicvoidbegin(long size) { downstream.begin(-1); }
@Override // 执行逻辑处理 publicvoidaccept(P_OUT u) { // 调用传入的方法进行处理元素 u ,u可能是 [1] [2] [3] [4,5] // 并将执行结果新的stream赋值给 result try (Stream<? extendsR> result = mapper.apply(u)) { // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it // 如果执行成功 返回了一个有效的 stream,则调用stream顺序流循环处理 downstream // 这里的 downstream就是 结果态节点 ReduceOp 也就是 collect 收集方法 if (result != null) result.sequential().forEach(downstream); } } }; } }; }
privatestaticfinalclassOfRef<T> extendsReferencePipeline.StatefulOp<T, T> { /** * Comparator used for sorting */ privatefinalboolean isNaturalSort; privatefinal Comparator<? super T> comparator;
/** * Sort using natural order of {@literal <T>} which must be * {@code Comparable}. */ OfRef(AbstractPipeline<?, T, ?> upstream) { super(upstream, StreamShape.REFERENCE, StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SORTED);
// 设置为自然有序 this.isNaturalSort = true; // Will throw CCE when we try to sort if T is not Comparable //设置排序方法为自然排序,如果是个不可排序的类型,将抛出异常 @SuppressWarnings("unchecked") Comparator<? super T> comp = (Comparator<? super T>) Comparator.naturalOrder(); this.comparator = comp; }
/** * Sort using the provided comparator. * * @param comparator The comparator to be used to evaluate ordering. */ OfRef(AbstractPipeline<?, T, ?> upstream, Comparator<? super T> comparator) { super(upstream, StreamShape.REFERENCE, StreamOpFlag.IS_ORDERED | StreamOpFlag.NOT_SORTED); // 非自然排序 this.isNaturalSort = false; // 将传入的排序方法赋值给排序方法 this.comparator = Objects.requireNonNull(comparator); }
@Override public Sink<T> opWrapSink(int flags, Sink<T> sink) { Objects.requireNonNull(sink);
// If the input is already naturally sorted and this operation // also naturally sorted then this is a no-op // 如果已经是有序的并且是自然排序的,就直接返回sink节点 if (StreamOpFlag.SORTED.isKnown(flags) && isNaturalSort) return sink; elseif (StreamOpFlag.SIZED.isKnown(flags)) // 如果标志位有 StreamOpFlag.SIZED,返回 SizedRefSortingSink 对象 returnnewSizedRefSortingSink<>(sink, comparator); else // 如果没有,返回 RefSortingSink 对象 returnnewRefSortingSink<>(sink, comparator); }
// 父类 包含一个比较器,继承自 Sink.ChainedReference privatestaticabstractclassAbstractRefSortingSink<T> extendsSink.ChainedReference<T, T> { protectedfinal Comparator<? super T> comparator; // @@@ could be a lazy final value, if/when support is added protectedboolean cancellationWasRequested;
AbstractRefSortingSink(Sink<? super T> downstream, Comparator<? super T> comparator) { // 调用父类的构造方法 super(downstream); // 比较器赋值 this.comparator = comparator; }
public DateTimeFormatterBuilder appendValue( TemporalField field, int minWidth, int maxWidth, SignStyle signStyle) { //这里不执行 忽略 if (minWidth == maxWidth && signStyle == SignStyle.NOT_NEGATIVE) { return appendValue(field, maxWidth); } //参数校验 Objects.requireNonNull(field, "field"); Objects.requireNonNull(signStyle, "signStyle"); //一些校验规则 if (minWidth < 1 || minWidth > 19) { thrownewIllegalArgumentException("The minimum width must be from 1 to 19 inclusive but was " + minWidth); } if (maxWidth < 1 || maxWidth > 19) { thrownewIllegalArgumentException("The maximum width must be from 1 to 19 inclusive but was " + maxWidth); } if (maxWidth < minWidth) { thrownewIllegalArgumentException("The maximum width must exceed or equal the minimum width but " + maxWidth + " < " + minWidth); } //重点是这里,创建了一个 NumberPrinterParser的对象,把参数传进去了。 NumberPrinterParserpp=newNumberPrinterParser(field, minWidth, maxWidth, signStyle); appendValue(pp); returnthis; }
//构造方法赋值 NumberPrinterParser(TemporalField field, int minWidth, int maxWidth, SignStyle signStyle) { // validated by caller this.field = field; this.minWidth = minWidth; this.maxWidth = maxWidth; this.signStyle = signStyle; this.subsequentWidth = 0; }
//格式化方法 @Override publicbooleanformat(DateTimePrintContext context, StringBuilder buf) { //从context上下文中获取字段 field = YEAR_OF_ERA context实际包含了真正的时间 2022-12-01T00:00:00 LongvalueLong= context.getValue(field); if (valueLong == null) { returnfalse; } //获取到以后 value = 2022 longvalue= getValue(context, valueLong); DecimalStyledecimalStyle= context.getDecimalStyle(); Stringstr= (value == Long.MIN_VALUE ? "9223372036854775808" : Long.toString(Math.abs(value))); if (str.length() > maxWidth) { thrownewDateTimeException("Field " + field + " cannot be printed as the value " + value + " exceeds the maximum print width of " + maxWidth); } //转换一个格式类型 str = decimalStyle.convertNumberToI18N(str);
//这些条件都不满足,忽略 if (value >= 0) { switch (signStyle) { case EXCEEDS_PAD: if (minWidth < 19 && value >= EXCEED_POINTS[minWidth]) { buf.append(decimalStyle.getPositiveSign()); } break; case ALWAYS: buf.append(decimalStyle.getPositiveSign()); break; } } else { switch (signStyle) { case NORMAL: case EXCEEDS_PAD: case ALWAYS: buf.append(decimalStyle.getNegativeSign()); break; case NOT_NEGATIVE: thrownewDateTimeException("Field " + field + " cannot be printed as the value " + value + " cannot be negative according to the SignStyle"); } } //填充0 也就是yyyy minWidth = 4就会填充0 MM minWidth = 2如果 1月就会填充01,一个M就不会走到循环填充0 for (inti=0; i < minWidth - str.length(); i++) { buf.append(decimalStyle.getZeroDigit()); } //输出到buf中 buf.append(str); returntrue; }
public DateTimeFormatterBuilder appendValue(TemporalField field, int width) { //参数校验 Objects.requireNonNull(field, "field"); if (width < 1 || width > 19) { thrownewIllegalArgumentException("The width must be from 1 to 19 inclusive but was " + width); } //可以发现MM也是用的yyyy这个解析器格式化的,但是后面三个参数不一样 NumberPrinterParserpp=newNumberPrinterParser(field, width, width, SignStyle.NOT_NEGATIVE); appendValue(pp); returnthis; }
privateintlocalizedWeekBasedYear(TemporalAccessor temporal) { //获取到这周的第几天 第5天 intdow= localizedDayOfWeek(temporal); //获取日期中的年份 2021 intyear= temporal.get(YEAR); //获取今年的第几天 2021-12-30 是 364天 intdoy= temporal.get(DAY_OF_YEAR); //这周开始的偏移量 5 intoffset= startOfWeekOffset(doy, dow); //今年的第几周 53周 intweek= computeWeek(offset, doy); //如果这周是0周,就是上一年的,年份就-1 if (week == 0) { // Day is in end of week of previous year; return the previous year return year - 1; } else { //如果接近年底,使用更高精度的逻辑 //检查 如果年份的日期包含在下一年的部分的星期里面了 // If getting close to end of year, use higher precision logic // Check if date of year is in partial week associated with next year //获取一年里面的天数 对象里面包含 最小1天 - 最大365天 ValueRangedayRange= temporal.range(DAY_OF_YEAR); //获取到年份的长度,也就是365 intyearLen= (int)dayRange.getMaximum(); //下一年的周数 根据下面的计算公式得出 (7 + 5 + 366 - 1) / 7 = 53 //这里为啥是366呢,因为yearLen是今年的天数也就是365 + 1,其实也就是到下一年去了。为的是计算下一年的第一周 intnewYearWeek= computeWeek(offset, yearLen + weekDef.getMinimalDaysInFirstWeek()); //比较如果今年的这周大于等于下一年的周 就年份 +1 所以这里格式化就会出错了。 if (week >= newYearWeek) { return year + 1; } } return year; }
privateintstartOfWeekOffset(int day, int dow) { // offset of first day corresponding to the day of week in first 7 days (zero origin) //算出上一周 (364 - 5) % 7 = 2 intweekStart= Math.floorMod(day - dow, 7); // offset = -2 intoffset= -weekStart; //这里 2 + 1 > 1会走进去 if (weekStart + 1 > weekDef.getMinimalDaysInFirstWeek()) { // The previous week has the minimum days in the current month to be a 'week' //这里 7 - 2 = 5 返回的就是5 offset = 7 - weekStart; } return offset; }
重点在这个配置,通过bean这个标签来告诉容器我要把哪些类注册到容器中,其中id就是注册后的唯一标识,我们获取的时候也可以通过指定id来从容器中获取对象。而class是告诉容器,我们具体要注入的类的路径。但是这时候没有指定参数,也就是说类似于Person person = new Person()这样的注册,需要有无参构造器。
y = 2^x的导数为ln2 * 2^x,x = 0代入为ln2 在点(0,1)处代入 y - 1 = ln2 (x - 0) y - 1 = ln2x - 0 y - ln2x - 1 = 0
导数
四则运算
1 2 3 4 5
d/dx (a+b) = d/dx a + d/dx b d/dx (a*b) = d/dxa * b + a * d/dx b d/dx (a/b) = (d/dxa * b - a * d/dx b) / b^2 d/dx (ca) = c * d/dx a, c为常数 d/dx (1/v) = -v^-2 * d/dx v