Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
83c573d4
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
83c573d4
编写于
6月 11, 2013
作者:
H
henryjen
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8009736: Comparator API cleanup
Reviewed-by: psandoz, briangoetz, mduigou, plevart
上级
071acd64
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
966 addition
and
478 deletion
+966
-478
src/share/classes/java/util/Collections.java
src/share/classes/java/util/Collections.java
+10
-0
src/share/classes/java/util/Comparator.java
src/share/classes/java/util/Comparator.java
+308
-37
src/share/classes/java/util/Comparators.java
src/share/classes/java/util/Comparators.java
+39
-222
src/share/classes/java/util/Map.java
src/share/classes/java/util/Map.java
+69
-0
src/share/classes/java/util/TreeMap.java
src/share/classes/java/util/TreeMap.java
+2
-2
src/share/classes/java/util/function/BinaryOperator.java
src/share/classes/java/util/function/BinaryOperator.java
+30
-0
src/share/classes/java/util/stream/Collectors.java
src/share/classes/java/util/stream/Collectors.java
+10
-11
src/share/classes/java/util/stream/ReferencePipeline.java
src/share/classes/java/util/stream/ReferencePipeline.java
+2
-3
src/share/classes/java/util/stream/SortedOps.java
src/share/classes/java/util/stream/SortedOps.java
+1
-2
test/java/nio/file/Files/StreamTest.java
test/java/nio/file/Files/StreamTest.java
+8
-8
test/java/util/Collection/ListDefaults.java
test/java/util/Collection/ListDefaults.java
+9
-10
test/java/util/Comparator/BasicTest.java
test/java/util/Comparator/BasicTest.java
+121
-164
test/java/util/Comparator/TypeTest.java
test/java/util/Comparator/TypeTest.java
+96
-0
test/java/util/Map/EntryComparators.java
test/java/util/Map/EntryComparators.java
+139
-0
test/java/util/function/BinaryOperator/BasicTest.java
test/java/util/function/BinaryOperator/BasicTest.java
+104
-0
test/java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java
.../org/openjdk/tests/java/util/stream/SequentialOpTest.java
+3
-4
test/java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java
.../test/org/openjdk/tests/java/util/stream/SliceOpTest.java
+1
-1
test/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java
...test/org/openjdk/tests/java/util/stream/SortedOpTest.java
+10
-10
test/sun/misc/JavaLangAccess/NewUnsafeString.java
test/sun/misc/JavaLangAccess/NewUnsafeString.java
+4
-4
未找到文件。
src/share/classes/java/util/Collections.java
浏览文件 @
83c573d4
...
@@ -4304,6 +4304,11 @@ public class Collections {
...
@@ -4304,6 +4304,11 @@ public class Collections {
}
}
private
Object
readResolve
()
{
return
Collections
.
reverseOrder
();
}
private
Object
readResolve
()
{
return
Collections
.
reverseOrder
();
}
@Override
public
Comparator
<
Comparable
<
Object
>>
reversed
()
{
return
Comparator
.
naturalOrder
();
}
}
}
/**
/**
...
@@ -4367,6 +4372,11 @@ public class Collections {
...
@@ -4367,6 +4372,11 @@ public class Collections {
public
int
hashCode
()
{
public
int
hashCode
()
{
return
cmp
.
hashCode
()
^
Integer
.
MIN_VALUE
;
return
cmp
.
hashCode
()
^
Integer
.
MIN_VALUE
;
}
}
@Override
public
Comparator
<
T
>
reversed
()
{
return
cmp
;
}
}
}
/**
/**
...
...
src/share/classes/java/util/Comparator.java
浏览文件 @
83c573d4
...
@@ -25,10 +25,12 @@
...
@@ -25,10 +25,12 @@
package
java.util
;
package
java.util
;
import
java.io.Serializable
;
import
java.util.function.Function
;
import
java.util.function.Function
;
import
java.util.function.ToIntFunction
;
import
java.util.function.ToIntFunction
;
import
java.util.function.ToLongFunction
;
import
java.util.function.ToLongFunction
;
import
java.util.function.ToDoubleFunction
;
import
java.util.function.ToDoubleFunction
;
import
java.util.Comparators
;
/**
/**
* A comparison function, which imposes a <i>total ordering</i> on some
* A comparison function, which imposes a <i>total ordering</i> on some
...
@@ -175,88 +177,357 @@ public interface Comparator<T> {
...
@@ -175,88 +177,357 @@ public interface Comparator<T> {
* Returns a comparator that imposes the reverse ordering of this
* Returns a comparator that imposes the reverse ordering of this
* comparator.
* comparator.
*
*
* @return
A
comparator that imposes the reverse ordering of this
* @return
a
comparator that imposes the reverse ordering of this
* comparator.
* comparator.
* @since 1.8
* @since 1.8
*/
*/
default
Comparator
<
T
>
reverse
Order
()
{
default
Comparator
<
T
>
reverse
d
()
{
return
Collections
.
reverseOrder
(
this
);
return
Collections
.
reverseOrder
(
this
);
}
}
/**
/**
* Constructs a lexicographic order comparator with another comparator.
* Returns a lexicographic-order comparator with another comparator.
* For example, a {@code Comparator<Person> byLastName} can be composed
* If this {@code Comparator} considers two elements equal, i.e.
* with another {@code Comparator<Person> byFirstName}, then {@code
* {@code compare(a, b) == 0}, {@code other} is used to determine the order.
* byLastName.thenComparing(byFirstName)} creates a {@code
*
* Comparator<Person>} which sorts by last name, and for equal last names
* <p>The returned comparator is serializable if the specified comparator
* sorts by first name.
* is also serializable.
*
*
* @param other the other comparator used when equals on this.
* @apiNote
* For example, to sort a collection of {@code String} based on the length
* and then case-insensitive natural ordering, the comparator can be
* composed using following code,
*
* <pre>{@code
* Comparator<String> cmp = Comparator.comparing(String::length)
* .thenComparing(String.CASE_INSENSITIVE_ORDER);
* }</pre>
*
* @param other the other comparator to be used when this comparator
* compares two objects that are equal.
* @return a lexicographic-order comparator composed of this and then the
* other comparator
* @throws NullPointerException if the argument is null.
* @throws NullPointerException if the argument is null.
* @since 1.8
* @since 1.8
*/
*/
default
Comparator
<
T
>
thenComparing
(
Comparator
<?
super
T
>
other
)
{
default
Comparator
<
T
>
thenComparing
(
Comparator
<?
super
T
>
other
)
{
return
Comparators
.
compose
(
this
,
other
);
Objects
.
requireNonNull
(
other
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
{
int
res
=
compare
(
c1
,
c2
);
return
(
res
!=
0
)
?
res
:
other
.
compare
(
c1
,
c2
);
};
}
}
/**
/**
* Constructs a lexicographic order comparator with a function that
* Returns a lexicographic-order comparator with a function that
* extracts a {@code Comparable} key. This default implementation calls
* extracts a key to be compared with the given {@code Comparator}.
* {@code thenComparing(this, Comparators.comparing(keyExtractor))}.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor, cmp))}.
*
*
* @param <U> the {@link Comparable} type for comparison
* @param <U> the type of the sort key
* @param keyExtractor the function used to extract the {@link Comparable} sort key
* @param keyExtractor the function used to extract the sort key
* @param keyComparator the {@code Comparator} used to compare the sort key
* @return a lexicographic-order comparator composed of this comparator
* and then comparing on the key extracted by the keyExtractor function
* @throws NullPointerException if the argument is null.
* @throws NullPointerException if the argument is null.
* @see
Comparators#comparing(Function
)
* @see
#comparing(Function, Comparator
)
* @see #thenComparing(Comparator)
* @see #thenComparing(Comparator)
* @since 1.8
* @since 1.8
*/
*/
default
<
U
extends
Comparable
<?
super
U
>>
Comparator
<
T
>
thenComparing
(
Function
<?
super
T
,
?
extends
U
>
keyExtractor
)
{
default
<
U
extends
Comparable
<?
super
U
>>
Comparator
<
T
>
thenComparing
(
return
thenComparing
(
Comparators
.
comparing
(
keyExtractor
));
Function
<?
super
T
,
?
extends
U
>
keyExtractor
,
Comparator
<?
super
U
>
keyComparator
)
{
return
thenComparing
(
comparing
(
keyExtractor
,
keyComparator
));
}
}
/**
/**
* Constructs a lexicographic order comparator with a function that
* Returns a lexicographic-order comparator with a function that
* extracts a {@code int} value. This default implementation calls {@code
* extracts a {@code Comparable} sort key.
* thenComparing(this, Comparators.comparing(keyExtractor))}.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
*
*
* @param keyExtractor the function used to extract the integer value
* @param <U> the type of the {@link Comparable} sort key
* @param keyExtractor the function used to extract the {@link
* Comparable} sort key
* @return a lexicographic-order comparator composed of this and then the
* {@link Comparable} sort key.
* @throws NullPointerException if the argument is null.
* @throws NullPointerException if the argument is null.
* @see Comparators#comparing(ToIntFunction)
* @see #comparing(Function)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default
<
U
extends
Comparable
<?
super
U
>>
Comparator
<
T
>
thenComparing
(
Function
<?
super
T
,
?
extends
U
>
keyExtractor
)
{
return
thenComparing
(
comparing
(
keyExtractor
));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code int} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
*
* @param keyExtractor the function used to extract the integer sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code int} sort key
* @throws NullPointerException if the argument is null.
* @see #comparing(ToIntFunction)
* @see #thenComparing(Comparator)
* @see #thenComparing(Comparator)
* @since 1.8
* @since 1.8
*/
*/
default
Comparator
<
T
>
thenComparing
(
ToIntFunction
<?
super
T
>
keyExtractor
)
{
default
Comparator
<
T
>
thenComparing
(
ToIntFunction
<?
super
T
>
keyExtractor
)
{
return
thenComparing
(
Comparators
.
comparing
(
keyExtractor
));
return
thenComparing
(
comparing
(
keyExtractor
));
}
}
/**
/**
* Constructs a lexicographic order comparator with a function that
* Returns a lexicographic-order comparator with a function that
* extracts a {@code long} value. This default implementation calls
* extracts a {@code long} sort key.
* {@code thenComparing(this, Comparators.comparing(keyExtractor))}.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
*
*
* @param keyExtractor the function used to extract the long value
* @param keyExtractor the function used to extract the long sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code long} sort key
* @throws NullPointerException if the argument is null.
* @throws NullPointerException if the argument is null.
* @see
Comparators
#comparing(ToLongFunction)
* @see #comparing(ToLongFunction)
* @see #thenComparing(Comparator)
* @see #thenComparing(Comparator)
* @since 1.8
* @since 1.8
*/
*/
default
Comparator
<
T
>
thenComparing
(
ToLongFunction
<?
super
T
>
keyExtractor
)
{
default
Comparator
<
T
>
thenComparing
(
ToLongFunction
<?
super
T
>
keyExtractor
)
{
return
thenComparing
(
Comparators
.
comparing
(
keyExtractor
));
return
thenComparing
(
comparing
(
keyExtractor
));
}
}
/**
/**
* Constructs a lexicographic order comparator with a function that
* Returns a lexicographic-order comparator with a function that
* extracts a {@code double} value. This default implementation calls
* extracts a {@code double} sort key.
* {@code thenComparing(this, Comparators.comparing(keyExtractor))}.
*
*
* @param keyExtractor the function used to extract the double value
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
*
* @param keyExtractor the function used to extract the double sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code double} sort key
* @throws NullPointerException if the argument is null.
* @throws NullPointerException if the argument is null.
* @see
Comparators
#comparing(ToDoubleFunction)
* @see #comparing(ToDoubleFunction)
* @see #thenComparing(Comparator)
* @see #thenComparing(Comparator)
* @since 1.8
* @since 1.8
*/
*/
default
Comparator
<
T
>
thenComparing
(
ToDoubleFunction
<?
super
T
>
keyExtractor
)
{
default
Comparator
<
T
>
thenComparing
(
ToDoubleFunction
<?
super
T
>
keyExtractor
)
{
return
thenComparing
(
Comparators
.
comparing
(
keyExtractor
));
return
thenComparing
(
comparing
(
keyExtractor
));
}
/**
* Returns a comparator that imposes the reverse of the <em>natural
* ordering</em>.
*
* <p>The returned comparator is serializable and throws {@link
* NullPointerException} when comparing {@code null}.
*
* @param <T> the {@link Comparable} type of element to be compared
* @return a comparator that imposes the reverse of the <i>natural
* ordering</i> on {@code Comparable} objects.
* @see Comparable
* @since 1.8
*/
public
static
<
T
extends
Comparable
<?
super
T
>>
Comparator
<
T
>
reverseOrder
()
{
return
Collections
.
reverseOrder
();
}
/**
* Returns a comparator that compares {@link Comparable} objects in natural
* order.
*
* <p>The returned comparator is serializable and throws {@link
* NullPointerException} when comparing {@code null}.
*
* @param <T> the {@link Comparable} type of element to be compared
* @return a comparator that imposes the <i>natural ordering</i> on {@code
* Comparable} objects.
* @see Comparable
* @since 1.8
*/
public
static
<
T
extends
Comparable
<?
super
T
>>
Comparator
<
T
>
naturalOrder
()
{
return
(
Comparator
<
T
>)
Comparators
.
NaturalOrderComparator
.
INSTANCE
;
}
/**
* Returns a null-friendly comparator that considers {@code null} to be
* less than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be less than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public
static
<
T
>
Comparator
<
T
>
nullsFirst
(
Comparator
<?
super
T
>
comparator
)
{
return
new
Comparators
.
NullComparator
(
true
,
comparator
);
}
/**
* Returns a null-friendly comparator that considers {@code null} to be
* greater than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be greater than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public
static
<
T
>
Comparator
<
T
>
nullsLast
(
Comparator
<?
super
T
>
comparator
)
{
return
new
Comparators
.
NullComparator
(
false
,
comparator
);
}
/**
* Accepts a function that extracts a sort key from a type {@code T}, and
* returns a {@code Comparator<T>} that compares by that sort key using
* the specified {@link Comparator}.
*
* <p>The returned comparator is serializable if the specified function
* and comparator are both serializable.
*
* @apiNote
* For example, to obtain a {@code Comparator} that compares {@code
* Person} objects by their last name ignoring case differences,
*
* <pre>{@code
* Comparator<Person> cmp = Comparator.comparing(
* Person::getLastName,
* String.CASE_INSENSITIVE_ORDER);
* }</pre>
*
* @param <T> the type of element to be compared
* @param <U> the type of the sort key
* @param keyExtractor the function used to extract the sort key
* @param keyComparator the {@code Comparator} used to compare the sort key
* @return a comparator that compares by an extracted key using the
* specified {@code Comparator}
* @throws NullPointerException if either argument is null
* @since 1.8
*/
public
static
<
T
,
U
>
Comparator
<
T
>
comparing
(
Function
<?
super
T
,
?
extends
U
>
keyExtractor
,
Comparator
<?
super
U
>
keyComparator
)
{
Objects
.
requireNonNull
(
keyExtractor
);
Objects
.
requireNonNull
(
keyComparator
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
keyComparator
.
compare
(
keyExtractor
.
apply
(
c1
),
keyExtractor
.
apply
(
c2
));
}
/**
* Accepts a function that extracts a {@link java.lang.Comparable
* Comparable} sort key from a type {@code T}, and returns a {@code
* Comparator<T>} that compares by that sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @apiNote
* For example, to obtain a {@code Comparator} that compares {@code
* Person} objects by their last name,
*
* <pre>{@code
* Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
* }</pre>
*
* @param <T> the type of element to be compared
* @param <U> the type of the {@code Comparable} sort key
* @param keyExtractor the function used to extract the {@link
* Comparable} sort key
* @return a comparator that compares by an extracted key
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public
static
<
T
,
U
extends
Comparable
<?
super
U
>>
Comparator
<
T
>
comparing
(
Function
<?
super
T
,
?
extends
U
>
keyExtractor
)
{
Objects
.
requireNonNull
(
keyExtractor
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
keyExtractor
.
apply
(
c1
).
compareTo
(
keyExtractor
.
apply
(
c2
));
}
/**
* Accepts a function that extracts an {@code int} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the integer sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public
static
<
T
>
Comparator
<
T
>
comparing
(
ToIntFunction
<?
super
T
>
keyExtractor
)
{
Objects
.
requireNonNull
(
keyExtractor
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
Integer
.
compare
(
keyExtractor
.
applyAsInt
(
c1
),
keyExtractor
.
applyAsInt
(
c2
));
}
/**
* Accepts a function that extracts a {@code long} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function is
* also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the long sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public
static
<
T
>
Comparator
<
T
>
comparing
(
ToLongFunction
<?
super
T
>
keyExtractor
)
{
Objects
.
requireNonNull
(
keyExtractor
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
Long
.
compare
(
keyExtractor
.
applyAsLong
(
c1
),
keyExtractor
.
applyAsLong
(
c2
));
}
/**
* Accepts a function that extracts a {@code double} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the double sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public
static
<
T
>
Comparator
<
T
>
comparing
(
ToDoubleFunction
<?
super
T
>
keyExtractor
)
{
Objects
.
requireNonNull
(
keyExtractor
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
Double
.
compare
(
keyExtractor
.
applyAsDouble
(
c1
),
keyExtractor
.
applyAsDouble
(
c2
));
}
}
}
}
src/share/classes/java/util/Comparators.java
浏览文件 @
83c573d4
/*
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012,
2013,
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -32,16 +32,9 @@ import java.util.function.ToIntFunction;
...
@@ -32,16 +32,9 @@ import java.util.function.ToIntFunction;
import
java.util.function.ToLongFunction
;
import
java.util.function.ToLongFunction
;
/**
/**
* This class consists of {@code static} utility methods for comparators. Mostly
* Package private supporting class for {@link Comparator}.
* factory method that returns a {@link Comparator}.
*
* <p> Unless otherwise noted, passing a {@code null} argument to a method in
* this class will cause a {@link NullPointerException} to be thrown.
*
* @see Comparator
* @since 1.8
*/
*/
public
class
Comparators
{
class
Comparators
{
private
Comparators
()
{
private
Comparators
()
{
throw
new
AssertionError
(
"no instances"
);
throw
new
AssertionError
(
"no instances"
);
}
}
...
@@ -51,231 +44,55 @@ public class Comparators {
...
@@ -51,231 +44,55 @@ public class Comparators {
*
*
* @see Comparable
* @see Comparable
*/
*/
private
enum
NaturalOrderComparator
implements
Comparator
<
Comparable
<
Object
>>
{
enum
NaturalOrderComparator
implements
Comparator
<
Comparable
<
Object
>>
{
INSTANCE
;
INSTANCE
;
@Override
@Override
public
int
compare
(
Comparable
<
Object
>
c1
,
Comparable
<
Object
>
c2
)
{
public
int
compare
(
Comparable
<
Object
>
c1
,
Comparable
<
Object
>
c2
)
{
return
c1
.
compareTo
(
c2
);
return
c1
.
compareTo
(
c2
);
}
}
}
/**
* Returns a comparator that imposes the reverse of the <em>natural
* ordering</em>.
*
* <p>The returned comparator is serializable.
*
* @param <T> {@link Comparable} type
*
* @return A comparator that imposes the reverse of the <i>natural
* ordering</i> on a collection of objects that implement
* the {@link Comparable} interface.
* @see Comparable
*/
public
static
<
T
extends
Comparable
<?
super
T
>>
Comparator
<
T
>
reverseOrder
()
{
return
Collections
.
reverseOrder
();
}
/**
* Returns a comparator that imposes the reverse ordering of the specified
* {@link Comparator}.
*
* <p>The returned comparator is serializable (assuming the specified
* comparator is also serializable).
*
* @param <T> the element type to be compared
* @param cmp a comparator whose ordering is to be reversed by the returned
* comparator
* @return A comparator that imposes the reverse ordering of the
* specified comparator.
*/
public
static
<
T
>
Comparator
<
T
>
reverseOrder
(
Comparator
<
T
>
cmp
)
{
Objects
.
requireNonNull
(
cmp
);
return
Collections
.
reverseOrder
(
cmp
);
}
/**
* Gets a comparator compares {@link Comparable} type in natural order.
*
* @param <T> {@link Comparable} type
*/
public
static
<
T
extends
Comparable
<?
super
T
>>
Comparator
<
T
>
naturalOrder
()
{
return
(
Comparator
<
T
>)
NaturalOrderComparator
.
INSTANCE
;
}
/**
* Gets a comparator compares {@link Map.Entry} in natural order on key.
*
* @param <K> {@link Comparable} key type
* @param <V> value type
*/
public
static
<
K
extends
Comparable
<?
super
K
>,
V
>
Comparator
<
Map
.
Entry
<
K
,
V
>>
naturalOrderKeys
()
{
return
(
Comparator
<
Map
.
Entry
<
K
,
V
>>
&
Serializable
)
(
c1
,
c2
)
->
c1
.
getKey
().
compareTo
(
c2
.
getKey
());
}
/**
* Gets a comparator compares {@link Map.Entry} in natural order on value.
*
* @param <K> key type
* @param <V> {@link Comparable} value type
*/
public
static
<
K
,
V
extends
Comparable
<?
super
V
>>
Comparator
<
Map
.
Entry
<
K
,
V
>>
naturalOrderValues
()
{
return
(
Comparator
<
Map
.
Entry
<
K
,
V
>>
&
Serializable
)
(
c1
,
c2
)
->
c1
.
getValue
().
compareTo
(
c2
.
getValue
());
}
/**
* Gets a comparator compares {@link Map.Entry} by key using the given
* {@link Comparator}.
*
* <p>The returned comparator is serializable assuming the specified
* comparators are also serializable.
*
* @param <K> key type
* @param <V> value type
* @param cmp the key {@link Comparator}
*/
public
static
<
K
,
V
>
Comparator
<
Map
.
Entry
<
K
,
V
>>
byKey
(
Comparator
<?
super
K
>
cmp
)
{
Objects
.
requireNonNull
(
cmp
);
return
(
Comparator
<
Map
.
Entry
<
K
,
V
>>
&
Serializable
)
(
c1
,
c2
)
->
cmp
.
compare
(
c1
.
getKey
(),
c2
.
getKey
());
}
/**
* Gets a comparator compares {@link Map.Entry} by value using the given
* {@link Comparator}.
*
* @param <K> key type
* @param <V> value type
* @param cmp the value {@link Comparator}
*/
public
static
<
K
,
V
>
Comparator
<
Map
.
Entry
<
K
,
V
>>
byValue
(
Comparator
<?
super
V
>
cmp
)
{
Objects
.
requireNonNull
(
cmp
);
return
(
Comparator
<
Map
.
Entry
<
K
,
V
>>
&
Serializable
)
(
c1
,
c2
)
->
cmp
.
compare
(
c1
.
getValue
(),
c2
.
getValue
());
}
/**
@Override
* Accepts a function that extracts a {@link java.lang.Comparable
public
Comparator
<
Comparable
<
Object
>>
reversed
()
{
* Comparable} sort key from a type {@code T}, and returns a {@code
return
Comparator
.
reverseOrder
();
* Comparator<T>} that compares by that sort key. For example, if a class
}
* {@code Person} has a {@code String}-valued getter {@code getLastName},
* then {@code comparing(Person::getLastName)} would return a {@code
* Comparator<Person>} that compares {@code Person} objects by their last
* name.
*
* @param <T> the original element type
* @param <U> the {@link Comparable} type for comparison
* @param keyExtractor the function used to extract the {@link Comparable} sort key
*/
public
static
<
T
,
U
extends
Comparable
<?
super
U
>>
Comparator
<
T
>
comparing
(
Function
<?
super
T
,
?
extends
U
>
keyExtractor
)
{
Objects
.
requireNonNull
(
keyExtractor
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
keyExtractor
.
apply
(
c1
).
compareTo
(
keyExtractor
.
apply
(
c2
));
}
/**
* Accepts a function that extracts an {@code int} value from a type {@code
* T}, and returns a {@code Comparator<T>} that compares by that value.
*
* <p>The returned comparator is serializable assuming the specified
* function is also serializable.
*
* @see #comparing(Function)
* @param <T> the original element type
* @param keyExtractor the function used to extract the integer value
*/
public
static
<
T
>
Comparator
<
T
>
comparing
(
ToIntFunction
<?
super
T
>
keyExtractor
)
{
Objects
.
requireNonNull
(
keyExtractor
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
Integer
.
compare
(
keyExtractor
.
applyAsInt
(
c1
),
keyExtractor
.
applyAsInt
(
c2
));
}
/**
* Accepts a function that extracts a {@code long} value from a type {@code
* T}, and returns a {@code Comparator<T>} that compares by that value.
*
* <p>The returned comparator is serializable assuming the specified
* function is also serializable.
*
* @see #comparing(Function)
* @param <T> the original element type
* @param keyExtractor the function used to extract the long value
*/
public
static
<
T
>
Comparator
<
T
>
comparing
(
ToLongFunction
<?
super
T
>
keyExtractor
)
{
Objects
.
requireNonNull
(
keyExtractor
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
Long
.
compare
(
keyExtractor
.
applyAsLong
(
c1
),
keyExtractor
.
applyAsLong
(
c2
));
}
}
/**
/**
* Accepts a function that extracts a {@code double} value from a type
* Null-friendly comparators
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* value.
*
* <p>The returned comparator is serializable assuming the specified
* function is also serializable.
*
* @see #comparing(Function)
* @param <T> the original element type
* @param keyExtractor the function used to extract the double value
*/
*/
public
static
<
T
>
Comparator
<
T
>
comparing
(
ToDoubleFunction
<?
super
T
>
keyExtractor
)
{
final
static
class
NullComparator
<
T
>
implements
Comparator
<
T
>,
Serializable
{
Objects
.
requireNonNull
(
keyExtractor
);
private
static
final
long
serialVersionUID
=
-
7569533591570686392L
;
return
(
Comparator
<
T
>
&
Serializable
)
private
final
boolean
nullFirst
;
(
c1
,
c2
)
->
Double
.
compare
(
keyExtractor
.
applyAsDouble
(
c1
),
keyExtractor
.
applyAsDouble
(
c2
));
// if null, non-null Ts are considered equal
}
private
final
Comparator
<
T
>
real
;
@SuppressWarnings
(
"unchecked"
)
NullComparator
(
boolean
nullFirst
,
Comparator
<?
super
T
>
real
)
{
this
.
nullFirst
=
nullFirst
;
this
.
real
=
(
Comparator
<
T
>)
real
;
}
/**
@Override
* Constructs a lexicographic order from two {@link Comparator}s. For
public
int
compare
(
T
a
,
T
b
)
{
* example, if you have comparators {@code byLastName} and {@code
if
(
a
==
null
)
{
* byFirstName}, each of type {@code Comparator<Person>}, then {@code
return
(
b
==
null
)
?
0
:
(
nullFirst
?
-
1
:
1
);
* compose(byLastName, byFirstName)} creates a {@code Comparator<Person>}
}
else
if
(
b
==
null
)
{
* which sorts by last name, and for equal last names sorts by first name.
return
nullFirst
?
1
:
-
1
;
*
}
else
{
* <p>The returned comparator is serializable assuming the specified
return
(
real
==
null
)
?
0
:
real
.
compare
(
a
,
b
);
* comparators are also serializable.
}
*
}
* @param <T> the element type to be compared
* @param first the first comparator
* @param second the secondary comparator used when equals on the first
*/
public
static
<
T
>
Comparator
<
T
>
compose
(
Comparator
<?
super
T
>
first
,
Comparator
<?
super
T
>
second
)
{
Objects
.
requireNonNull
(
first
);
Objects
.
requireNonNull
(
second
);
return
(
Comparator
<
T
>
&
Serializable
)
(
c1
,
c2
)
->
{
int
res
=
first
.
compare
(
c1
,
c2
);
return
(
res
!=
0
)
?
res
:
second
.
compare
(
c1
,
c2
);
};
}
/**
@Override
* Constructs a {@link BinaryOperator} which returns the lesser of two elements
public
Comparator
<
T
>
thenComparing
(
Comparator
<?
super
T
>
other
)
{
* according to the specified {@code Comparator}
Objects
.
requireNonNull
(
other
);
*
return
new
NullComparator
(
nullFirst
,
real
==
null
?
other
:
real
.
thenComparing
(
other
));
* @param comparator A {@code Comparator} for comparing the two values
}
* @param <T> the type of the elements to be compared
* @return a {@code BinaryOperator} which returns the lesser of its operands,
* according to the supplied {@code Comparator}
*/
public
static
<
T
>
BinaryOperator
<
T
>
lesserOf
(
Comparator
<?
super
T
>
comparator
)
{
Objects
.
requireNonNull
(
comparator
);
return
(
a
,
b
)
->
comparator
.
compare
(
a
,
b
)
<=
0
?
a
:
b
;
}
/**
@Override
* Constructs a {@link BinaryOperator} which returns the greater of two elements
public
Comparator
<
T
>
reversed
()
{
* according to the specified {@code Comparator}
return
new
NullComparator
(!
nullFirst
,
real
==
null
?
null
:
real
.
reversed
());
*
}
* @param comparator A {@code Comparator} for comparing the two values
* @param <T> the type of the elements to be compared
* @return a {@code BinaryOperator} which returns the greater of its operands,
* according to the supplied {@code Comparator}
*/
public
static
<
T
>
BinaryOperator
<
T
>
greaterOf
(
Comparator
<?
super
T
>
comparator
)
{
Objects
.
requireNonNull
(
comparator
);
return
(
a
,
b
)
->
comparator
.
compare
(
a
,
b
)
>=
0
?
a
:
b
;
}
}
}
}
src/share/classes/java/util/Map.java
浏览文件 @
83c573d4
...
@@ -28,6 +28,7 @@ package java.util;
...
@@ -28,6 +28,7 @@ package java.util;
import
java.util.function.BiConsumer
;
import
java.util.function.BiConsumer
;
import
java.util.function.BiFunction
;
import
java.util.function.BiFunction
;
import
java.util.function.Function
;
import
java.util.function.Function
;
import
java.io.Serializable
;
/**
/**
* An object that maps keys to values. A map cannot contain duplicate keys;
* An object that maps keys to values. A map cannot contain duplicate keys;
...
@@ -446,6 +447,74 @@ public interface Map<K,V> {
...
@@ -446,6 +447,74 @@ public interface Map<K,V> {
* @see #equals(Object)
* @see #equals(Object)
*/
*/
int
hashCode
();
int
hashCode
();
/**
* Returns a comparator that compares {@link Map.Entry} in natural order on key.
*
* <p>The returned comparator is serializable and throws {@link
* NullPointerException} when comparing an entry with a null key.
*
* @param <K> the {@link Comparable} type of then map keys
* @param <V> the type of the map values
* @return a comparator that compares {@link Map.Entry} in natural order on key.
* @see Comparable
*/
public
static
<
K
extends
Comparable
<?
super
K
>,
V
>
Comparator
<
Map
.
Entry
<
K
,
V
>>
comparingByKey
()
{
return
(
Comparator
<
Map
.
Entry
<
K
,
V
>>
&
Serializable
)
(
c1
,
c2
)
->
c1
.
getKey
().
compareTo
(
c2
.
getKey
());
}
/**
* Returns a comparator that compares {@link Map.Entry} in natural order on value.
*
* <p>The returned comparator is serializable and throws {@link
* NullPointerException} when comparing an entry with null values.
*
* @param <K> the type of the map keys
* @param <V> the {@link Comparable} type of the map values
* @return a comparator that compares {@link Map.Entry} in natural order on value.
* @see Comparable
*/
public
static
<
K
,
V
extends
Comparable
<?
super
V
>>
Comparator
<
Map
.
Entry
<
K
,
V
>>
comparingByValue
()
{
return
(
Comparator
<
Map
.
Entry
<
K
,
V
>>
&
Serializable
)
(
c1
,
c2
)
->
c1
.
getValue
().
compareTo
(
c2
.
getValue
());
}
/**
* Returns a comparator that compares {@link Map.Entry} by key using the given
* {@link Comparator}.
*
* <p>The returned comparator is serializable if the specified comparator
* is also serializable.
*
* @param <K> the type of the map keys
* @param <V> the type of the map values
* @param cmp the key {@link Comparator}
* @return a comparator that compares {@link Map.Entry} by the key.
*/
public
static
<
K
,
V
>
Comparator
<
Map
.
Entry
<
K
,
V
>>
comparingByKey
(
Comparator
<?
super
K
>
cmp
)
{
Objects
.
requireNonNull
(
cmp
);
return
(
Comparator
<
Map
.
Entry
<
K
,
V
>>
&
Serializable
)
(
c1
,
c2
)
->
cmp
.
compare
(
c1
.
getKey
(),
c2
.
getKey
());
}
/**
* Returns a comparator that compares {@link Map.Entry} by value using the given
* {@link Comparator}.
*
* <p>The returned comparator is serializable if the specified comparator
* is also serializable.
*
* @param <K> the type of the map keys
* @param <V> the type of the map values
* @param cmp the value {@link Comparator}
* @return a comparator that compares {@link Map.Entry} by the value.
*/
public
static
<
K
,
V
>
Comparator
<
Map
.
Entry
<
K
,
V
>>
comparingByValue
(
Comparator
<?
super
V
>
cmp
)
{
Objects
.
requireNonNull
(
cmp
);
return
(
Comparator
<
Map
.
Entry
<
K
,
V
>>
&
Serializable
)
(
c1
,
c2
)
->
cmp
.
compare
(
c1
.
getValue
(),
c2
.
getValue
());
}
}
}
// Comparison and hashing
// Comparison and hashing
...
...
src/share/classes/java/util/TreeMap.java
浏览文件 @
83c573d4
...
@@ -2938,13 +2938,13 @@ public class TreeMap<K,V>
...
@@ -2938,13 +2938,13 @@ public class TreeMap<K,V>
public
int
characteristics
()
{
public
int
characteristics
()
{
return
(
side
==
0
?
Spliterator
.
SIZED
:
0
)
|
return
(
side
==
0
?
Spliterator
.
SIZED
:
0
)
|
Spliterator
.
DISTINCT
|
Spliterator
.
SORTED
|
Spliterator
.
ORDERED
;
Spliterator
.
DISTINCT
|
Spliterator
.
SORTED
|
Spliterator
.
ORDERED
;
}
}
@Override
@Override
public
Comparator
<?
super
Map
.
Entry
<
K
,
V
>>
getComparator
()
{
public
Comparator
<?
super
Map
.
Entry
<
K
,
V
>>
getComparator
()
{
return
tree
.
comparator
!=
null
?
return
tree
.
comparator
!=
null
?
Comparators
.
b
yKey
(
tree
.
comparator
)
:
null
;
Map
.
Entry
.
comparingB
yKey
(
tree
.
comparator
)
:
null
;
}
}
}
}
}
}
src/share/classes/java/util/function/BinaryOperator.java
浏览文件 @
83c573d4
...
@@ -24,6 +24,9 @@
...
@@ -24,6 +24,9 @@
*/
*/
package
java.util.function
;
package
java.util.function
;
import
java.util.Objects
;
import
java.util.Comparator
;
/**
/**
* An operation upon two operands yielding a result. This is a specialization of
* An operation upon two operands yielding a result. This is a specialization of
* {@code BiFunction} where the operands and the result are all of the same type.
* {@code BiFunction} where the operands and the result are all of the same type.
...
@@ -35,4 +38,31 @@ package java.util.function;
...
@@ -35,4 +38,31 @@ package java.util.function;
*/
*/
@FunctionalInterface
@FunctionalInterface
public
interface
BinaryOperator
<
T
>
extends
BiFunction
<
T
,
T
,
T
>
{
public
interface
BinaryOperator
<
T
>
extends
BiFunction
<
T
,
T
,
T
>
{
/**
* Returns a {@link BinaryOperator} which returns the lesser of two elements
* according to the specified {@code Comparator}
*
* @param comparator a {@code Comparator} for comparing the two values
* @return a {@code BinaryOperator} which returns the lesser of its operands,
* according to the supplied {@code Comparator}
* @throws NullPointerException if the argument is null
*/
public
static
<
T
>
BinaryOperator
<
T
>
minBy
(
Comparator
<?
super
T
>
comparator
)
{
Objects
.
requireNonNull
(
comparator
);
return
(
a
,
b
)
->
comparator
.
compare
(
a
,
b
)
<=
0
?
a
:
b
;
}
/**
* Returns a {@link BinaryOperator} which returns the greater of two elements
* according to the specified {@code Comparator}
*
* @param comparator a {@code Comparator} for comparing the two values
* @return a {@code BinaryOperator} which returns the greater of its operands,
* according to the supplied {@code Comparator}
* @throws NullPointerException if the argument is null
*/
public
static
<
T
>
BinaryOperator
<
T
>
maxBy
(
Comparator
<?
super
T
>
comparator
)
{
Objects
.
requireNonNull
(
comparator
);
return
(
a
,
b
)
->
comparator
.
compare
(
a
,
b
)
>=
0
?
a
:
b
;
}
}
}
src/share/classes/java/util/stream/Collectors.java
浏览文件 @
83c573d4
...
@@ -30,7 +30,6 @@ import java.util.ArrayList;
...
@@ -30,7 +30,6 @@ import java.util.ArrayList;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.Comparator
;
import
java.util.Comparators
;
import
java.util.DoubleSummaryStatistics
;
import
java.util.DoubleSummaryStatistics
;
import
java.util.EnumSet
;
import
java.util.EnumSet
;
import
java.util.HashMap
;
import
java.util.HashMap
;
...
@@ -78,7 +77,7 @@ import java.util.function.ToLongFunction;
...
@@ -78,7 +77,7 @@ import java.util.function.ToLongFunction;
*
*
* // Find highest-paid employee
* // Find highest-paid employee
* Employee highestPaid = employees.stream()
* Employee highestPaid = employees.stream()
* .collect(Collectors.maxBy(Comparator
s
.comparing(Employee::getSalary)));
* .collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary)));
*
*
* // Group employees by department
* // Group employees by department
* Map<Department, List<Employee>> byDept
* Map<Department, List<Employee>> byDept
...
@@ -89,7 +88,7 @@ import java.util.function.ToLongFunction;
...
@@ -89,7 +88,7 @@ import java.util.function.ToLongFunction;
* Map<Department, Employee> highestPaidByDept
* Map<Department, Employee> highestPaidByDept
* = employees.stream()
* = employees.stream()
* .collect(Collectors.groupingBy(Employee::getDepartment,
* .collect(Collectors.groupingBy(Employee::getDepartment,
* Collectors.maxBy(Comparator
s
.comparing(Employee::getSalary))));
* Collectors.maxBy(Comparator.comparing(Employee::getSalary))));
*
*
* // Partition students into passing and failing
* // Partition students into passing and failing
* Map<Boolean, List<Student>> passingFailing =
* Map<Boolean, List<Student>> passingFailing =
...
@@ -404,7 +403,7 @@ public final class Collectors {
...
@@ -404,7 +403,7 @@ public final class Collectors {
* @implSpec
* @implSpec
* This produces a result equivalent to:
* This produces a result equivalent to:
* <pre>{@code
* <pre>{@code
* reducing(
Comparators.lesserOf
(comparator))
* reducing(
BinaryOperator.minBy
(comparator))
* }</pre>
* }</pre>
*
*
* @param <T> the type of the input elements
* @param <T> the type of the input elements
...
@@ -413,7 +412,7 @@ public final class Collectors {
...
@@ -413,7 +412,7 @@ public final class Collectors {
*/
*/
public
static
<
T
>
Collector
<
T
,
T
>
public
static
<
T
>
Collector
<
T
,
T
>
minBy
(
Comparator
<?
super
T
>
comparator
)
{
minBy
(
Comparator
<?
super
T
>
comparator
)
{
return
reducing
(
Comparators
.
lesserOf
(
comparator
));
return
reducing
(
BinaryOperator
.
minBy
(
comparator
));
}
}
/**
/**
...
@@ -423,7 +422,7 @@ public final class Collectors {
...
@@ -423,7 +422,7 @@ public final class Collectors {
* @implSpec
* @implSpec
* This produces a result equivalent to:
* This produces a result equivalent to:
* <pre>{@code
* <pre>{@code
* reducing(
Comparators.greaterOf
(comparator))
* reducing(
BinaryOperator.maxBy
(comparator))
* }</pre>
* }</pre>
*
*
* @param <T> the type of the input elements
* @param <T> the type of the input elements
...
@@ -432,7 +431,7 @@ public final class Collectors {
...
@@ -432,7 +431,7 @@ public final class Collectors {
*/
*/
public
static
<
T
>
Collector
<
T
,
T
>
public
static
<
T
>
Collector
<
T
,
T
>
maxBy
(
Comparator
<?
super
T
>
comparator
)
{
maxBy
(
Comparator
<?
super
T
>
comparator
)
{
return
reducing
(
Comparators
.
greaterOf
(
comparator
));
return
reducing
(
BinaryOperator
.
maxBy
(
comparator
));
}
}
/**
/**
...
@@ -491,8 +490,8 @@ public final class Collectors {
...
@@ -491,8 +490,8 @@ public final class Collectors {
* <p>For example, given a stream of {@code Person}, to calculate tallest
* <p>For example, given a stream of {@code Person}, to calculate tallest
* person in each city:
* person in each city:
* <pre>{@code
* <pre>{@code
* Comparator<Person> byHeight = Comparator
s
.comparing(Person::getHeight);
* Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
* BinaryOperator<Person> tallerOf =
Comparators
.greaterOf(byHeight);
* BinaryOperator<Person> tallerOf =
BinaryOperator
.greaterOf(byHeight);
* Map<City, Person> tallestByCity
* Map<City, Person> tallestByCity
* = people.stream().collect(groupingBy(Person::getCity, reducing(tallerOf)));
* = people.stream().collect(groupingBy(Person::getCity, reducing(tallerOf)));
* }</pre>
* }</pre>
...
@@ -531,8 +530,8 @@ public final class Collectors {
...
@@ -531,8 +530,8 @@ public final class Collectors {
* <p>For example, given a stream of {@code Person}, to calculate the longest
* <p>For example, given a stream of {@code Person}, to calculate the longest
* last name of residents in each city:
* last name of residents in each city:
* <pre>{@code
* <pre>{@code
* Comparator<String> byLength = Comparator
s
.comparing(String::length);
* Comparator<String> byLength = Comparator.comparing(String::length);
* BinaryOperator<String> longerOf =
Comparators
.greaterOf(byLength);
* BinaryOperator<String> longerOf =
BinaryOperator
.greaterOf(byLength);
* Map<City, String> longestLastNameByCity
* Map<City, String> longestLastNameByCity
* = people.stream().collect(groupingBy(Person::getCity,
* = people.stream().collect(groupingBy(Person::getCity,
* reducing(Person::getLastName, longerOf)));
* reducing(Person::getLastName, longerOf)));
...
...
src/share/classes/java/util/stream/ReferencePipeline.java
浏览文件 @
83c573d4
...
@@ -25,7 +25,6 @@
...
@@ -25,7 +25,6 @@
package
java.util.stream
;
package
java.util.stream
;
import
java.util.Comparator
;
import
java.util.Comparator
;
import
java.util.Comparators
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.Objects
;
import
java.util.Objects
;
import
java.util.Optional
;
import
java.util.Optional
;
...
@@ -512,12 +511,12 @@ abstract class ReferencePipeline<P_IN, P_OUT>
...
@@ -512,12 +511,12 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
@Override
public
final
Optional
<
P_OUT
>
max
(
Comparator
<?
super
P_OUT
>
comparator
)
{
public
final
Optional
<
P_OUT
>
max
(
Comparator
<?
super
P_OUT
>
comparator
)
{
return
reduce
(
Comparators
.
greaterOf
(
comparator
));
return
reduce
(
BinaryOperator
.
maxBy
(
comparator
));
}
}
@Override
@Override
public
final
Optional
<
P_OUT
>
min
(
Comparator
<?
super
P_OUT
>
comparator
)
{
public
final
Optional
<
P_OUT
>
min
(
Comparator
<?
super
P_OUT
>
comparator
)
{
return
reduce
(
Comparators
.
lesserOf
(
comparator
));
return
reduce
(
BinaryOperator
.
minBy
(
comparator
));
}
}
...
...
src/share/classes/java/util/stream/SortedOps.java
浏览文件 @
83c573d4
...
@@ -27,7 +27,6 @@ package java.util.stream;
...
@@ -27,7 +27,6 @@ package java.util.stream;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Comparator
;
import
java.util.Comparator
;
import
java.util.Comparators
;
import
java.util.Objects
;
import
java.util.Objects
;
import
java.util.Spliterator
;
import
java.util.Spliterator
;
import
java.util.concurrent.ForkJoinTask
;
import
java.util.concurrent.ForkJoinTask
;
...
@@ -114,7 +113,7 @@ final class SortedOps {
...
@@ -114,7 +113,7 @@ final class SortedOps {
StreamOpFlag
.
IS_ORDERED
|
StreamOpFlag
.
IS_SORTED
);
StreamOpFlag
.
IS_ORDERED
|
StreamOpFlag
.
IS_SORTED
);
this
.
isNaturalSort
=
true
;
this
.
isNaturalSort
=
true
;
// Will throw CCE when we try to sort if T is not Comparable
// Will throw CCE when we try to sort if T is not Comparable
this
.
comparator
=
(
Comparator
<?
super
T
>)
Comparator
s
.
naturalOrder
();
this
.
comparator
=
(
Comparator
<?
super
T
>)
Comparator
.
naturalOrder
();
}
}
/**
/**
...
...
test/java/nio/file/Files/StreamTest.java
浏览文件 @
83c573d4
...
@@ -43,7 +43,7 @@ import java.nio.file.Path;
...
@@ -43,7 +43,7 @@ import java.nio.file.Path;
import
java.nio.file.Paths
;
import
java.nio.file.Paths
;
import
java.nio.file.attribute.BasicFileAttributes
;
import
java.nio.file.attribute.BasicFileAttributes
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Comparator
s
;
import
java.util.Comparator
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Objects
;
...
@@ -139,7 +139,7 @@ public class StreamTest {
...
@@ -139,7 +139,7 @@ public class StreamTest {
public
void
testBasic
()
{
public
void
testBasic
()
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
list
(
testFolder
))
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
list
(
testFolder
))
{
Object
[]
actual
=
s
.
sorted
(
Comparator
s
.
naturalOrder
()).
toArray
();
Object
[]
actual
=
s
.
sorted
(
Comparator
.
naturalOrder
()).
toArray
();
assertEquals
(
actual
,
level1
);
assertEquals
(
actual
,
level1
);
}
catch
(
IOException
ioe
)
{
}
catch
(
IOException
ioe
)
{
fail
(
"Unexpected IOException"
);
fail
(
"Unexpected IOException"
);
...
@@ -155,7 +155,7 @@ public class StreamTest {
...
@@ -155,7 +155,7 @@ public class StreamTest {
public
void
testWalk
()
{
public
void
testWalk
()
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
walk
(
testFolder
))
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
walk
(
testFolder
))
{
Object
[]
actual
=
s
.
sorted
(
Comparator
s
.
naturalOrder
()).
toArray
();
Object
[]
actual
=
s
.
sorted
(
Comparator
.
naturalOrder
()).
toArray
();
assertEquals
(
actual
,
all
);
assertEquals
(
actual
,
all
);
}
catch
(
IOException
ioe
)
{
}
catch
(
IOException
ioe
)
{
fail
(
"Unexpected IOException"
);
fail
(
"Unexpected IOException"
);
...
@@ -165,7 +165,7 @@ public class StreamTest {
...
@@ -165,7 +165,7 @@ public class StreamTest {
public
void
testWalkOneLevel
()
{
public
void
testWalkOneLevel
()
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
walk
(
testFolder
,
1
))
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
walk
(
testFolder
,
1
))
{
Object
[]
actual
=
s
.
filter
(
path
->
!
path
.
equals
(
testFolder
))
Object
[]
actual
=
s
.
filter
(
path
->
!
path
.
equals
(
testFolder
))
.
sorted
(
Comparator
s
.
naturalOrder
())
.
sorted
(
Comparator
.
naturalOrder
())
.
toArray
();
.
toArray
();
assertEquals
(
actual
,
level1
);
assertEquals
(
actual
,
level1
);
}
catch
(
IOException
ioe
)
{
}
catch
(
IOException
ioe
)
{
...
@@ -177,7 +177,7 @@ public class StreamTest {
...
@@ -177,7 +177,7 @@ public class StreamTest {
// If link is not supported, the directory structure won't have link.
// If link is not supported, the directory structure won't have link.
// We still want to test the behavior with FOLLOW_LINKS option.
// We still want to test the behavior with FOLLOW_LINKS option.
try
(
CloseableStream
<
Path
>
s
=
Files
.
walk
(
testFolder
,
FileVisitOption
.
FOLLOW_LINKS
))
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
walk
(
testFolder
,
FileVisitOption
.
FOLLOW_LINKS
))
{
Object
[]
actual
=
s
.
sorted
(
Comparator
s
.
naturalOrder
()).
toArray
();
Object
[]
actual
=
s
.
sorted
(
Comparator
.
naturalOrder
()).
toArray
();
assertEquals
(
actual
,
all_folowLinks
);
assertEquals
(
actual
,
all_folowLinks
);
}
catch
(
IOException
ioe
)
{
}
catch
(
IOException
ioe
)
{
fail
(
"Unexpected IOException"
);
fail
(
"Unexpected IOException"
);
...
@@ -637,13 +637,13 @@ public class StreamTest {
...
@@ -637,13 +637,13 @@ public class StreamTest {
public
void
testClosedStream
()
throws
IOException
{
public
void
testClosedStream
()
throws
IOException
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
list
(
testFolder
))
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
list
(
testFolder
))
{
s
.
close
();
s
.
close
();
Object
[]
actual
=
s
.
sorted
(
Comparator
s
.
naturalOrder
()).
toArray
();
Object
[]
actual
=
s
.
sorted
(
Comparator
.
naturalOrder
()).
toArray
();
assertTrue
(
actual
.
length
<=
level1
.
length
);
assertTrue
(
actual
.
length
<=
level1
.
length
);
}
}
try
(
CloseableStream
<
Path
>
s
=
Files
.
walk
(
testFolder
))
{
try
(
CloseableStream
<
Path
>
s
=
Files
.
walk
(
testFolder
))
{
s
.
close
();
s
.
close
();
Object
[]
actual
=
s
.
sorted
(
Comparator
s
.
naturalOrder
()).
toArray
();
Object
[]
actual
=
s
.
sorted
(
Comparator
.
naturalOrder
()).
toArray
();
fail
(
"Operate on closed stream should throw IllegalStateException"
);
fail
(
"Operate on closed stream should throw IllegalStateException"
);
}
catch
(
IllegalStateException
ex
)
{
}
catch
(
IllegalStateException
ex
)
{
// expected
// expected
...
@@ -652,7 +652,7 @@ public class StreamTest {
...
@@ -652,7 +652,7 @@ public class StreamTest {
try
(
CloseableStream
<
Path
>
s
=
Files
.
find
(
testFolder
,
Integer
.
MAX_VALUE
,
try
(
CloseableStream
<
Path
>
s
=
Files
.
find
(
testFolder
,
Integer
.
MAX_VALUE
,
(
p
,
attr
)
->
true
))
{
(
p
,
attr
)
->
true
))
{
s
.
close
();
s
.
close
();
Object
[]
actual
=
s
.
sorted
(
Comparator
s
.
naturalOrder
()).
toArray
();
Object
[]
actual
=
s
.
sorted
(
Comparator
.
naturalOrder
()).
toArray
();
fail
(
"Operate on closed stream should throw IllegalStateException"
);
fail
(
"Operate on closed stream should throw IllegalStateException"
);
}
catch
(
IllegalStateException
ex
)
{
}
catch
(
IllegalStateException
ex
)
{
// expected
// expected
...
...
test/java/util/Collection/ListDefaults.java
浏览文件 @
83c573d4
...
@@ -25,7 +25,6 @@ import java.util.ArrayList;
...
@@ -25,7 +25,6 @@ import java.util.ArrayList;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.Comparator
;
import
java.util.Comparators
;
import
java.util.List
;
import
java.util.List
;
import
java.util.LinkedList
;
import
java.util.LinkedList
;
import
java.util.Stack
;
import
java.util.Stack
;
...
@@ -337,23 +336,23 @@ public class ListDefaults {
...
@@ -337,23 +336,23 @@ public class ListDefaults {
CollectionSupplier
.
shuffle
(
list
);
CollectionSupplier
.
shuffle
(
list
);
list
.
sort
(
null
);
list
.
sort
(
null
);
CollectionAsserts
.
assertSorted
(
list
,
Comparator
s
.<
Integer
>
naturalOrder
());
CollectionAsserts
.
assertSorted
(
list
,
Comparator
.<
Integer
>
naturalOrder
());
if
(
test
.
name
.
startsWith
(
"reverse"
))
{
if
(
test
.
name
.
startsWith
(
"reverse"
))
{
Collections
.
reverse
(
list
);
Collections
.
reverse
(
list
);
}
}
CollectionAsserts
.
assertContents
(
list
,
original
);
CollectionAsserts
.
assertContents
(
list
,
original
);
CollectionSupplier
.
shuffle
(
list
);
CollectionSupplier
.
shuffle
(
list
);
list
.
sort
(
Comparator
s
.<
Integer
>
naturalOrder
());
list
.
sort
(
Comparator
.<
Integer
>
naturalOrder
());
CollectionAsserts
.
assertSorted
(
list
,
Comparator
s
.<
Integer
>
naturalOrder
());
CollectionAsserts
.
assertSorted
(
list
,
Comparator
.<
Integer
>
naturalOrder
());
if
(
test
.
name
.
startsWith
(
"reverse"
))
{
if
(
test
.
name
.
startsWith
(
"reverse"
))
{
Collections
.
reverse
(
list
);
Collections
.
reverse
(
list
);
}
}
CollectionAsserts
.
assertContents
(
list
,
original
);
CollectionAsserts
.
assertContents
(
list
,
original
);
CollectionSupplier
.
shuffle
(
list
);
CollectionSupplier
.
shuffle
(
list
);
list
.
sort
(
Comparator
s
.<
Integer
>
reverseOrder
());
list
.
sort
(
Comparator
.<
Integer
>
reverseOrder
());
CollectionAsserts
.
assertSorted
(
list
,
Comparator
s
.<
Integer
>
reverseOrder
());
CollectionAsserts
.
assertSorted
(
list
,
Comparator
.<
Integer
>
reverseOrder
());
if
(!
test
.
name
.
startsWith
(
"reverse"
))
{
if
(!
test
.
name
.
startsWith
(
"reverse"
))
{
Collections
.
reverse
(
list
);
Collections
.
reverse
(
list
);
}
}
...
@@ -390,8 +389,8 @@ public class ListDefaults {
...
@@ -390,8 +389,8 @@ public class ListDefaults {
final
List
<
Integer
>
copy
=
new
ArrayList
<>(
list
);
final
List
<
Integer
>
copy
=
new
ArrayList
<>(
list
);
final
List
<
Integer
>
subList
=
list
.
subList
(
SUBLIST_FROM
,
SUBLIST_TO
);
final
List
<
Integer
>
subList
=
list
.
subList
(
SUBLIST_FROM
,
SUBLIST_TO
);
CollectionSupplier
.
shuffle
(
subList
);
CollectionSupplier
.
shuffle
(
subList
);
subList
.
sort
(
Comparator
s
.<
Integer
>
naturalOrder
());
subList
.
sort
(
Comparator
.<
Integer
>
naturalOrder
());
CollectionAsserts
.
assertSorted
(
subList
,
Comparator
s
.<
Integer
>
naturalOrder
());
CollectionAsserts
.
assertSorted
(
subList
,
Comparator
.<
Integer
>
naturalOrder
());
// verify that elements [0, from) remain unmodified
// verify that elements [0, from) remain unmodified
for
(
int
i
=
0
;
i
<
SUBLIST_FROM
;
i
++)
{
for
(
int
i
=
0
;
i
<
SUBLIST_FROM
;
i
++)
{
assertTrue
(
list
.
get
(
i
)
==
copy
.
get
(
i
),
assertTrue
(
list
.
get
(
i
)
==
copy
.
get
(
i
),
...
@@ -412,8 +411,8 @@ public class ListDefaults {
...
@@ -412,8 +411,8 @@ public class ListDefaults {
public
void
call
(
final
List
<
Integer
>
list
)
{
public
void
call
(
final
List
<
Integer
>
list
)
{
final
List
<
Integer
>
copy
=
new
ArrayList
<>(
list
);
final
List
<
Integer
>
copy
=
new
ArrayList
<>(
list
);
CollectionSupplier
.
shuffle
(
list
);
CollectionSupplier
.
shuffle
(
list
);
list
.
sort
(
Comparator
s
.<
Integer
>
naturalOrder
());
list
.
sort
(
Comparator
.<
Integer
>
naturalOrder
());
CollectionAsserts
.
assertSorted
(
list
,
Comparator
s
.<
Integer
>
naturalOrder
());
CollectionAsserts
.
assertSorted
(
list
,
Comparator
.<
Integer
>
naturalOrder
());
}
}
});
});
}
}
...
...
test/java/util/Comparator
s
/BasicTest.java
→
test/java/util/Comparator/BasicTest.java
浏览文件 @
83c573d4
/*
/*
* Copyright (c) 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 201
3
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -21,19 +21,16 @@
...
@@ -21,19 +21,16 @@
* questions.
* questions.
*/
*/
/*
/*
*
* @test
* @test
* @
bug 8001667 8010279
* @
summary Comparator default method tests
* @run testng BasicTest
* @run testng BasicTest
*/
*/
import
java.util.TreeMap
;
import
java.util.Comparator
;
import
java.util.Comparator
;
import
java.util.Comparators
;
import
java.util.AbstractMap
;
import
java.util.Map
;
import
org.testng.annotations.Test
;
import
org.testng.annotations.Test
;
import
java.util.function.BinaryOperator
;
import
java.util.function.Function
;
import
java.util.function.Function
;
import
java.util.function.ToIntFunction
;
import
java.util.function.ToIntFunction
;
import
java.util.function.ToLongFunction
;
import
java.util.function.ToLongFunction
;
...
@@ -41,12 +38,8 @@ import java.util.function.ToDoubleFunction;
...
@@ -41,12 +38,8 @@ import java.util.function.ToDoubleFunction;
import
static
org
.
testng
.
Assert
.
assertEquals
;
import
static
org
.
testng
.
Assert
.
assertEquals
;
import
static
org
.
testng
.
Assert
.
assertTrue
;
import
static
org
.
testng
.
Assert
.
assertTrue
;
import
static
org
.
testng
.
Assert
.
assertSame
;
import
static
org
.
testng
.
Assert
.
fail
;
import
static
org
.
testng
.
Assert
.
fail
;
/**
* Unit tests for helper methods in Comparators
*/
@Test
(
groups
=
"unit"
)
@Test
(
groups
=
"unit"
)
public
class
BasicTest
{
public
class
BasicTest
{
private
static
class
Thing
{
private
static
class
Thing
{
...
@@ -97,7 +90,7 @@ public class BasicTest {
...
@@ -97,7 +90,7 @@ public class BasicTest {
Thing
[]
things
=
new
Thing
[
intValues
.
length
];
Thing
[]
things
=
new
Thing
[
intValues
.
length
];
for
(
int
i
=
0
;
i
<
intValues
.
length
;
i
++)
for
(
int
i
=
0
;
i
<
intValues
.
length
;
i
++)
things
[
i
]
=
new
Thing
(
intValues
[
i
],
0L
,
0.0
,
null
);
things
[
i
]
=
new
Thing
(
intValues
[
i
],
0L
,
0.0
,
null
);
Comparator
<
Thing
>
comp
=
Comparator
s
.
comparing
(
new
ToIntFunction
<
BasicTest
.
Thing
>()
{
Comparator
<
Thing
>
comp
=
Comparator
.
comparing
(
new
ToIntFunction
<
Thing
>()
{
@Override
@Override
public
int
applyAsInt
(
Thing
thing
)
{
public
int
applyAsInt
(
Thing
thing
)
{
return
thing
.
getIntField
();
return
thing
.
getIntField
();
...
@@ -111,7 +104,7 @@ public class BasicTest {
...
@@ -111,7 +104,7 @@ public class BasicTest {
Thing
[]
things
=
new
Thing
[
longValues
.
length
];
Thing
[]
things
=
new
Thing
[
longValues
.
length
];
for
(
int
i
=
0
;
i
<
longValues
.
length
;
i
++)
for
(
int
i
=
0
;
i
<
longValues
.
length
;
i
++)
things
[
i
]
=
new
Thing
(
0
,
longValues
[
i
],
0.0
,
null
);
things
[
i
]
=
new
Thing
(
0
,
longValues
[
i
],
0.0
,
null
);
Comparator
<
Thing
>
comp
=
Comparator
s
.
comparing
(
new
ToLongFunction
<
BasicTest
.
Thing
>()
{
Comparator
<
Thing
>
comp
=
Comparator
.
comparing
(
new
ToLongFunction
<
Thing
>()
{
@Override
@Override
public
long
applyAsLong
(
Thing
thing
)
{
public
long
applyAsLong
(
Thing
thing
)
{
return
thing
.
getLongField
();
return
thing
.
getLongField
();
...
@@ -125,7 +118,7 @@ public class BasicTest {
...
@@ -125,7 +118,7 @@ public class BasicTest {
Thing
[]
things
=
new
Thing
[
doubleValues
.
length
];
Thing
[]
things
=
new
Thing
[
doubleValues
.
length
];
for
(
int
i
=
0
;
i
<
doubleValues
.
length
;
i
++)
for
(
int
i
=
0
;
i
<
doubleValues
.
length
;
i
++)
things
[
i
]
=
new
Thing
(
0
,
0L
,
doubleValues
[
i
],
null
);
things
[
i
]
=
new
Thing
(
0
,
0L
,
doubleValues
[
i
],
null
);
Comparator
<
Thing
>
comp
=
Comparator
s
.
comparing
(
new
ToDoubleFunction
<
BasicTest
.
Thing
>()
{
Comparator
<
Thing
>
comp
=
Comparator
.
comparing
(
new
ToDoubleFunction
<
Thing
>()
{
@Override
@Override
public
double
applyAsDouble
(
Thing
thing
)
{
public
double
applyAsDouble
(
Thing
thing
)
{
return
thing
.
getDoubleField
();
return
thing
.
getDoubleField
();
...
@@ -139,7 +132,7 @@ public class BasicTest {
...
@@ -139,7 +132,7 @@ public class BasicTest {
Thing
[]
things
=
new
Thing
[
doubleValues
.
length
];
Thing
[]
things
=
new
Thing
[
doubleValues
.
length
];
for
(
int
i
=
0
;
i
<
doubleValues
.
length
;
i
++)
for
(
int
i
=
0
;
i
<
doubleValues
.
length
;
i
++)
things
[
i
]
=
new
Thing
(
0
,
0L
,
0.0
,
stringValues
[
i
]);
things
[
i
]
=
new
Thing
(
0
,
0L
,
0.0
,
stringValues
[
i
]);
Comparator
<
Thing
>
comp
=
Comparator
s
.
comparing
(
new
Function
<
Thing
,
String
>()
{
Comparator
<
Thing
>
comp
=
Comparator
.
comparing
(
new
Function
<
Thing
,
String
>()
{
@Override
@Override
public
String
apply
(
Thing
thing
)
{
public
String
apply
(
Thing
thing
)
{
return
thing
.
getStringField
();
return
thing
.
getStringField
();
...
@@ -150,16 +143,16 @@ public class BasicTest {
...
@@ -150,16 +143,16 @@ public class BasicTest {
}
}
public
void
testNaturalOrderComparator
()
{
public
void
testNaturalOrderComparator
()
{
Comparator
<
String
>
comp
=
Comparator
s
.
naturalOrder
();
Comparator
<
String
>
comp
=
Comparator
.
naturalOrder
();
assertComparisons
(
stringValues
,
comp
,
comparisons
);
assertComparisons
(
stringValues
,
comp
,
comparisons
);
}
}
public
void
testReverseComparator
()
{
public
void
testReverseComparator
()
{
Comparator
<
String
>
cmpr
=
Comparator
s
.
reverseOrder
();
Comparator
<
String
>
cmpr
=
Comparator
.
reverseOrder
();
Comparator
<
String
>
cmp
=
cmpr
.
reverse
Order
();
Comparator
<
String
>
cmp
=
cmpr
.
reverse
d
();
assertEquals
(
cmp
.
reverse
Order
(),
cmpr
);
assertEquals
(
cmp
.
reverse
d
(),
cmpr
);
assertEquals
(
0
,
cmp
.
compare
(
"a"
,
"a"
));
assertEquals
(
0
,
cmp
.
compare
(
"a"
,
"a"
));
assertEquals
(
0
,
cmpr
.
compare
(
"a"
,
"a"
));
assertEquals
(
0
,
cmpr
.
compare
(
"a"
,
"a"
));
assertTrue
(
cmp
.
compare
(
"a"
,
"b"
)
<
0
);
assertTrue
(
cmp
.
compare
(
"a"
,
"b"
)
<
0
);
...
@@ -170,9 +163,9 @@ public class BasicTest {
...
@@ -170,9 +163,9 @@ public class BasicTest {
public
void
testReverseComparator2
()
{
public
void
testReverseComparator2
()
{
Comparator
<
String
>
cmp
=
(
s1
,
s2
)
->
s1
.
length
()
-
s2
.
length
();
Comparator
<
String
>
cmp
=
(
s1
,
s2
)
->
s1
.
length
()
-
s2
.
length
();
Comparator
<
String
>
cmpr
=
cmp
.
reverse
Order
();
Comparator
<
String
>
cmpr
=
cmp
.
reverse
d
();
assertEquals
(
cmpr
.
reverse
Order
(),
cmp
);
assertEquals
(
cmpr
.
reverse
d
(),
cmp
);
assertEquals
(
0
,
cmp
.
compare
(
"abc"
,
"def"
));
assertEquals
(
0
,
cmp
.
compare
(
"abc"
,
"def"
));
assertEquals
(
0
,
cmpr
.
compare
(
"abc"
,
"def"
));
assertEquals
(
0
,
cmpr
.
compare
(
"abc"
,
"def"
));
assertTrue
(
cmp
.
compare
(
"abcd"
,
"def"
)
>
0
);
assertTrue
(
cmp
.
compare
(
"abcd"
,
"def"
)
>
0
);
...
@@ -181,71 +174,11 @@ public class BasicTest {
...
@@ -181,71 +174,11 @@ public class BasicTest {
assertTrue
(
cmpr
.
compare
(
"abc"
,
"defg"
)
>
0
);
assertTrue
(
cmpr
.
compare
(
"abc"
,
"defg"
)
>
0
);
}
}
@Test
(
expectedExceptions
=
NullPointerException
.
class
)
private
<
T
>
void
assertComparison
(
Comparator
<
T
>
cmp
,
T
less
,
T
greater
)
{
public
void
testReverseComparatorNPE
()
{
assertTrue
(
cmp
.
compare
(
less
,
greater
)
<
0
,
"less"
);
Comparator
<
String
>
cmp
=
Comparators
.
reverseOrder
(
null
);
assertTrue
(
cmp
.
compare
(
less
,
less
)
==
0
,
"equal"
);
}
assertTrue
(
cmp
.
compare
(
greater
,
greater
)
==
0
,
"equal"
);
assertTrue
(
cmp
.
compare
(
greater
,
less
)
>
0
,
"greater"
);
public
void
testComposeComparator
()
{
// Longer string in front
Comparator
<
String
>
first
=
(
s1
,
s2
)
->
s2
.
length
()
-
s1
.
length
();
Comparator
<
String
>
second
=
Comparators
.
naturalOrder
();
Comparator
<
String
>
composed
=
Comparators
.
compose
(
first
,
second
);
assertTrue
(
composed
.
compare
(
"abcdefg"
,
"abcdef"
)
<
0
);
assertTrue
(
composed
.
compare
(
"abcdef"
,
"abcdefg"
)
>
0
);
assertTrue
(
composed
.
compare
(
"abcdef"
,
"abcdef"
)
==
0
);
assertTrue
(
composed
.
compare
(
"abcdef"
,
"ghijkl"
)
<
0
);
assertTrue
(
composed
.
compare
(
"ghijkl"
,
"abcdefg"
)
>
0
);
}
private
<
K
,
V
>
void
assertPairComparison
(
K
k1
,
V
v1
,
K
k2
,
V
v2
,
Comparator
<
Map
.
Entry
<
K
,
V
>>
ck
,
Comparator
<
Map
.
Entry
<
K
,
V
>>
cv
)
{
final
Map
.
Entry
<
K
,
V
>
p11
=
new
AbstractMap
.
SimpleImmutableEntry
<>(
k1
,
v1
);
final
Map
.
Entry
<
K
,
V
>
p12
=
new
AbstractMap
.
SimpleImmutableEntry
<>(
k1
,
v2
);
final
Map
.
Entry
<
K
,
V
>
p21
=
new
AbstractMap
.
SimpleImmutableEntry
<>(
k2
,
v1
);
final
Map
.
Entry
<
K
,
V
>
p22
=
new
AbstractMap
.
SimpleImmutableEntry
<>(
k2
,
v2
);
assertTrue
(
ck
.
compare
(
p11
,
p11
)
==
0
);
assertTrue
(
ck
.
compare
(
p12
,
p11
)
==
0
);
assertTrue
(
ck
.
compare
(
p11
,
p12
)
==
0
);
assertTrue
(
ck
.
compare
(
p12
,
p22
)
<
0
);
assertTrue
(
ck
.
compare
(
p12
,
p21
)
<
0
);
assertTrue
(
ck
.
compare
(
p21
,
p11
)
>
0
);
assertTrue
(
ck
.
compare
(
p21
,
p12
)
>
0
);
assertTrue
(
cv
.
compare
(
p11
,
p11
)
==
0
);
assertTrue
(
cv
.
compare
(
p12
,
p11
)
>
0
);
assertTrue
(
cv
.
compare
(
p11
,
p12
)
<
0
);
assertTrue
(
cv
.
compare
(
p12
,
p22
)
==
0
);
assertTrue
(
cv
.
compare
(
p12
,
p21
)
>
0
);
assertTrue
(
cv
.
compare
(
p21
,
p11
)
==
0
);
assertTrue
(
cv
.
compare
(
p21
,
p12
)
<
0
);
Comparator
<
Map
.
Entry
<
K
,
V
>>
cmp
=
Comparators
.
compose
(
ck
,
cv
);
assertTrue
(
cmp
.
compare
(
p11
,
p11
)
==
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p11
)
>
0
);
assertTrue
(
cmp
.
compare
(
p11
,
p12
)
<
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p22
)
<
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p21
)
<
0
);
assertTrue
(
cmp
.
compare
(
p21
,
p11
)
>
0
);
assertTrue
(
cmp
.
compare
(
p21
,
p12
)
>
0
);
cmp
=
Comparators
.
compose
(
cv
,
ck
);
assertTrue
(
cmp
.
compare
(
p11
,
p11
)
==
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p11
)
>
0
);
assertTrue
(
cmp
.
compare
(
p11
,
p12
)
<
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p22
)
<
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p21
)
>
0
);
assertTrue
(
cmp
.
compare
(
p21
,
p11
)
>
0
);
assertTrue
(
cmp
.
compare
(
p21
,
p12
)
<
0
);
}
public
void
testKVComparatorable
()
{
assertPairComparison
(
1
,
"ABC"
,
2
,
"XYZ"
,
Comparators
.<
Integer
,
String
>
naturalOrderKeys
(),
Comparators
.<
Integer
,
String
>
naturalOrderValues
());
}
}
private
static
class
People
{
private
static
class
People
{
...
@@ -273,33 +206,15 @@ public class BasicTest {
...
@@ -273,33 +206,15 @@ public class BasicTest {
new
People
(
"Jonah"
,
"Doe"
,
10
),
new
People
(
"Jonah"
,
"Doe"
,
10
),
new
People
(
"John"
,
"Cook"
,
54
),
new
People
(
"John"
,
"Cook"
,
54
),
new
People
(
"Mary"
,
"Cook"
,
50
),
new
People
(
"Mary"
,
"Cook"
,
50
),
new
People
(
"Mary"
,
null
,
25
),
new
People
(
"John"
,
null
,
27
)
};
};
public
void
testKVComparators
()
{
// Comparator<People> cmp = Comparators.naturalOrder(); // Should fail to compiler as People is not comparable
// We can use simple comparator, but those have been tested above.
// Thus choose to do compose for some level of interation.
Comparator
<
People
>
cmp1
=
Comparators
.
comparing
((
Function
<
People
,
String
>)
People:
:
getFirstName
);
Comparator
<
People
>
cmp2
=
Comparators
.
comparing
((
Function
<
People
,
String
>)
People:
:
getLastName
);
Comparator
<
People
>
cmp
=
Comparators
.
compose
(
cmp1
,
cmp2
);
assertPairComparison
(
people
[
0
],
people
[
0
],
people
[
1
],
people
[
1
],
Comparators
.<
People
,
People
>
byKey
(
cmp
),
Comparators
.<
People
,
People
>
byValue
(
cmp
));
}
private
<
T
>
void
assertComparison
(
Comparator
<
T
>
cmp
,
T
less
,
T
greater
)
{
assertTrue
(
cmp
.
compare
(
less
,
greater
)
<
0
,
"less"
);
assertTrue
(
cmp
.
compare
(
less
,
less
)
==
0
,
"equal"
);
assertTrue
(
cmp
.
compare
(
greater
,
less
)
>
0
,
"greater"
);
}
public
void
testComparatorDefaultMethods
()
{
public
void
testComparatorDefaultMethods
()
{
Comparator
<
People
>
cmp
=
Comparator
s
.
comparing
((
Function
<
People
,
String
>)
People:
:
getFirstName
);
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getFirstName
);
Comparator
<
People
>
cmp2
=
Comparator
s
.
comparing
((
Function
<
People
,
String
>)
People:
:
getLastName
);
Comparator
<
People
>
cmp2
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getLastName
);
// reverseOrder
// reverseOrder
assertComparison
(
cmp
.
reverse
Order
(),
people
[
1
],
people
[
0
]);
assertComparison
(
cmp
.
reverse
d
(),
people
[
1
],
people
[
0
]);
// thenComparing(Comparator)
// thenComparing(Comparator)
assertComparison
(
cmp
.
thenComparing
(
cmp2
),
people
[
0
],
people
[
1
]);
assertComparison
(
cmp
.
thenComparing
(
cmp2
),
people
[
0
],
people
[
1
]);
assertComparison
(
cmp
.
thenComparing
(
cmp2
),
people
[
4
],
people
[
0
]);
assertComparison
(
cmp
.
thenComparing
(
cmp2
),
people
[
4
],
people
[
0
]);
...
@@ -317,96 +232,138 @@ public class BasicTest {
...
@@ -317,96 +232,138 @@ public class BasicTest {
assertComparison
(
cmp
.
thenComparing
(
People:
:
getAgeAsDouble
),
people
[
1
],
people
[
5
]);
assertComparison
(
cmp
.
thenComparing
(
People:
:
getAgeAsDouble
),
people
[
1
],
people
[
5
]);
}
}
public
void
testGreaterOf
()
{
// lesser
public
void
testNullsFirst
()
{
assertSame
(
Comparators
.
greaterOf
(
Comparators
.
comparing
(
Comparator
<
String
>
strcmp
=
Comparator
.
nullsFirst
(
Comparator
.
naturalOrder
());
(
Function
<
People
,
String
>)
People:
:
getFirstName
))
Comparator
<
People
>
cmp
=
Comparator
.<
People
,
String
>
comparing
(
People:
:
getLastName
,
strcmp
)
.
apply
(
people
[
0
],
people
[
1
]),
.
thenComparing
(
People:
:
getFirstName
,
strcmp
);
people
[
1
]);
// Mary.null vs Mary.Cook - solve by last name
// euqal
assertComparison
(
cmp
,
people
[
6
],
people
[
5
]);
assertSame
(
Comparators
.
greaterOf
(
Comparators
.
comparing
(
// John.null vs Mary.null - solve by first name
(
Function
<
People
,
String
>)
People:
:
getLastName
))
assertComparison
(
cmp
,
people
[
7
],
people
[
6
]);
.
apply
(
people
[
0
],
people
[
1
]),
people
[
0
]);
// More than one thenComparing
// greater
strcmp
=
Comparator
.
nullsFirst
(
Comparator
.
comparing
((
ToIntFunction
<
String
>)
String:
:
length
)
assertSame
(
Comparators
.
greaterOf
(
Comparators
.
comparing
(
.
thenComparing
(
String
.
CASE_INSENSITIVE_ORDER
));
(
ToIntFunction
<
People
>)
People:
:
getAge
))
assertComparison
(
strcmp
,
null
,
"abc"
);
.
apply
(
people
[
0
],
people
[
1
]),
assertComparison
(
strcmp
,
"ab"
,
"abc"
);
people
[
0
]);
assertComparison
(
strcmp
,
"abc"
,
"def"
);
assertEquals
(
0
,
strcmp
.
compare
(
"abc"
,
"ABC"
));
// Ensure reverse still handle null properly
Comparator
<
String
>
strcmp2
=
strcmp
.
reversed
().
thenComparing
(
Comparator
.
naturalOrder
());
assertComparison
(
strcmp2
,
"abc"
,
null
);
assertComparison
(
strcmp2
,
"abc"
,
"ab"
);
assertComparison
(
strcmp2
,
"def"
,
"abc"
);
assertComparison
(
strcmp2
,
"ABC"
,
"abc"
);
// Considering non-null values to be equal
Comparator
<
String
>
blind
=
Comparator
.
nullsFirst
(
null
);
assertComparison
(
blind
,
null
,
"abc"
);
assertEquals
(
0
,
blind
.
compare
(
"abc"
,
"def"
));
// reverse still consider non-null values to be equal
strcmp
=
blind
.
reversed
();
assertComparison
(
strcmp
,
"abc"
,
null
);
assertEquals
(
0
,
strcmp
.
compare
(
"abc"
,
"def"
));
// chain with another comparator to compare non-nulls
strcmp
=
blind
.
thenComparing
(
Comparator
.
naturalOrder
());
assertComparison
(
strcmp
,
null
,
"abc"
);
assertComparison
(
strcmp
,
"abc"
,
"def"
);
}
public
void
testNullsLast
()
{
Comparator
<
String
>
strcmp
=
Comparator
.
nullsLast
(
Comparator
.
naturalOrder
());
Comparator
<
People
>
cmp
=
Comparator
.<
People
,
String
>
comparing
(
People:
:
getLastName
,
strcmp
)
.
thenComparing
(
People:
:
getFirstName
,
strcmp
);
// Mary.null vs Mary.Cook - solve by last name
assertComparison
(
cmp
,
people
[
5
],
people
[
6
]);
// John.null vs Mary.null - solve by first name
assertComparison
(
cmp
,
people
[
7
],
people
[
6
]);
// More than one thenComparing
strcmp
=
Comparator
.
nullsLast
(
Comparator
.
comparing
((
ToIntFunction
<
String
>)
String:
:
length
)
.
thenComparing
(
String
.
CASE_INSENSITIVE_ORDER
));
assertComparison
(
strcmp
,
"abc"
,
null
);
assertComparison
(
strcmp
,
"ab"
,
"abc"
);
assertComparison
(
strcmp
,
"abc"
,
"def"
);
// Ensure reverse still handle null properly
Comparator
<
String
>
strcmp2
=
strcmp
.
reversed
().
thenComparing
(
Comparator
.
naturalOrder
());
assertComparison
(
strcmp2
,
null
,
"abc"
);
assertComparison
(
strcmp2
,
"abc"
,
"ab"
);
assertComparison
(
strcmp2
,
"def"
,
"abc"
);
assertComparison
(
strcmp2
,
"ABC"
,
"abc"
);
// Considering non-null values to be equal
Comparator
<
String
>
blind
=
Comparator
.
nullsLast
(
null
);
assertComparison
(
blind
,
"abc"
,
null
);
assertEquals
(
0
,
blind
.
compare
(
"abc"
,
"def"
));
// reverse still consider non-null values to be equal
strcmp
=
blind
.
reversed
();
assertComparison
(
strcmp
,
null
,
"abc"
);
assertEquals
(
0
,
strcmp
.
compare
(
"abc"
,
"def"
));
// chain with another comparator to compare non-nulls
strcmp
=
blind
.
thenComparing
(
Comparator
.
naturalOrder
());
assertComparison
(
strcmp
,
"abc"
,
null
);
assertComparison
(
strcmp
,
"abc"
,
"def"
);
}
}
public
void
testLesserOf
()
{
public
void
testComposeComparator
()
{
// lesser
// Longer string in front
assertSame
(
Comparators
.
lesserOf
(
Comparators
.
comparing
(
Comparator
<
String
>
first
=
(
s1
,
s2
)
->
s2
.
length
()
-
s1
.
length
();
(
Function
<
People
,
String
>)
People:
:
getFirstName
))
Comparator
<
String
>
second
=
Comparator
.
naturalOrder
();
.
apply
(
people
[
0
],
people
[
1
]),
Comparator
<
String
>
composed
=
first
.
thenComparing
(
second
);
people
[
0
]);
// euqal
assertTrue
(
composed
.
compare
(
"abcdefg"
,
"abcdef"
)
<
0
);
assertSame
(
Comparators
.
lesserOf
(
Comparators
.
comparing
(
assertTrue
(
composed
.
compare
(
"abcdef"
,
"abcdefg"
)
>
0
);
(
Function
<
People
,
String
>)
People:
:
getLastName
))
assertTrue
(
composed
.
compare
(
"abcdef"
,
"abcdef"
)
==
0
);
.
apply
(
people
[
0
],
people
[
1
]),
assertTrue
(
composed
.
compare
(
"abcdef"
,
"ghijkl"
)
<
0
);
people
[
0
]);
assertTrue
(
composed
.
compare
(
"ghijkl"
,
"abcdefg"
)
>
0
);
// greater
assertSame
(
Comparators
.
lesserOf
(
Comparators
.
comparing
(
(
ToIntFunction
<
People
>)
People:
:
getAge
))
.
apply
(
people
[
0
],
people
[
1
]),
people
[
1
]);
}
}
public
void
testNulls
()
{
public
void
testNulls
()
{
try
{
try
{
Comparator
s
.<
String
>
naturalOrder
().
compare
(
"abc"
,
(
String
)
null
);
Comparator
.<
String
>
naturalOrder
().
compare
(
"abc"
,
(
String
)
null
);
fail
(
"expected NPE with naturalOrder"
);
fail
(
"expected NPE with naturalOrder"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
s
.<
String
>
naturalOrder
().
compare
((
String
)
null
,
"abc"
);
Comparator
.<
String
>
naturalOrder
().
compare
((
String
)
null
,
"abc"
);
fail
(
"expected NPE with naturalOrder"
);
fail
(
"expected NPE with naturalOrder"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
s
.<
String
>
reverseOrder
().
compare
(
"abc"
,
(
String
)
null
);
Comparator
.<
String
>
reverseOrder
().
compare
(
"abc"
,
(
String
)
null
);
fail
(
"expected NPE with naturalOrder"
);
fail
(
"expected NPE with naturalOrder"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
s
.<
String
>
reverseOrder
().
compare
((
String
)
null
,
"abc"
);
Comparator
.<
String
>
reverseOrder
().
compare
((
String
)
null
,
"abc"
);
fail
(
"expected NPE with naturalOrder"
);
fail
(
"expected NPE with naturalOrder"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
<
Map
.
Entry
<
String
,
String
>>
cmp
=
Comparators
.
byKey
(
null
);
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
null
,
Comparator
.<
String
>
naturalOrder
()
);
fail
(
"
byKey(null
) should throw NPE"
);
fail
(
"
comparing(null, cmp
) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
<
Map
.
Entry
<
String
,
String
>>
cmp
=
Comparators
.
byValue
(
null
);
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getFirstName
,
null
);
fail
(
"
byValue(
null) should throw NPE"
);
fail
(
"
comparing(f,
null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
<
People
>
cmp
=
Comparator
s
.
comparing
((
Function
<
People
,
String
>)
null
);
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
null
);
fail
(
"comparing(null) should throw NPE"
);
fail
(
"comparing(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
<
People
>
cmp
=
Comparator
s
.
comparing
((
ToIntFunction
<
People
>)
null
);
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
ToIntFunction
<
People
>)
null
);
fail
(
"comparing(null) should throw NPE"
);
fail
(
"comparing(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
<
People
>
cmp
=
Comparator
s
.
comparing
((
ToLongFunction
<
People
>)
null
);
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
ToLongFunction
<
People
>)
null
);
fail
(
"comparing(null) should throw NPE"
);
fail
(
"comparing(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
try
{
Comparator
<
People
>
cmp
=
Comparator
s
.
comparing
((
ToDoubleFunction
<
People
>)
null
);
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
ToDoubleFunction
<
People
>)
null
);
fail
(
"comparing(null) should throw NPE"
);
fail
(
"comparing(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
catch
(
NullPointerException
npe
)
{}
try
{
BinaryOperator
<
String
>
op
=
Comparators
.
lesserOf
(
null
);
fail
(
"lesserOf(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
try
{
BinaryOperator
<
String
>
op
=
Comparators
.
greaterOf
(
null
);
fail
(
"lesserOf(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
}
}
}
test/java/util/Comparator/TypeTest.java
0 → 100644
浏览文件 @
83c573d4
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Comparator API narrowing type test
* @run testng TypeTest
*/
import
java.util.function.Function
;
import
java.util.Map
;
import
java.util.TreeMap
;
import
java.util.Comparator
;
import
org.testng.annotations.Test
;
@Test
(
groups
=
"unit"
)
public
class
TypeTest
{
static
class
Person
{
String
name
;
static
Comparator
<
Person
>
C
=
(
p1
,
p2
)
->
p1
.
name
.
compareTo
(
p2
.
name
);
Person
(
String
name
)
{
this
.
name
=
name
;
}
String
getName
()
{
return
name
;
}
}
static
class
Employee
extends
Person
{
int
id
;
static
Comparator
<
Employee
>
C
=
(
e1
,
e2
)
->
e1
.
id
-
e2
.
id
;
Employee
(
int
id
,
String
name
)
{
super
(
name
);
this
.
id
=
id
;
}
}
static
class
Manager
extends
Employee
{
long
reports
;
static
Comparator
<
Manager
>
C
=
(
e1
,
e2
)
->
(
int
)
(
e1
.
reports
-
e2
.
reports
);
Manager
(
String
name
,
int
id
,
long
reports
)
{
super
(
id
,
name
);
this
.
reports
=
reports
;
}
}
static
<
T
>
void
assertOrder
(
T
o1
,
T
o2
,
Comparator
<?
super
T
>
cmp
)
{
if
(
cmp
.
compare
(
o1
,
o2
)
>
0
)
{
System
.
out
.
println
(
"Fail!!"
);
}
if
(
cmp
.
compare
(
o1
,
o2
)
==
0
)
{
System
.
out
.
println
(
"Equal!!"
);
}
}
public
static
void
main
(
String
[]
args
)
{
Manager
m1
=
new
Manager
(
"Manager"
,
2
,
2000
);
Manager
m2
=
new
Manager
(
"Manager"
,
4
,
1300
);
// Comparator<Employee> tmp = Person.C;
// Comparator<Manager> cmp = Employee.C.thenComparing(Person.C);
Comparator
<
Employee
>
cmp
=
Employee
.
C
.
thenComparing
(
Person
.
C
);
assertOrder
(
m1
,
m2
,
Employee
.
C
.
thenComparing
(
Person
.
C
));
assertOrder
(
m1
,
m2
,
cmp
);
assertOrder
(
m1
,
new
Employee
(
1
,
"Z"
),
Person
.
C
);
assertOrder
(
new
Employee
(
1
,
"Z"
),
m2
,
Employee
.
C
);
assertOrder
(
m1
,
m2
,
Comparator
.
comparing
(
Employee:
:
getName
,
String
.
CASE_INSENSITIVE_ORDER
));
Map
<
String
,
Integer
>
map
=
new
TreeMap
<>();
map
.
entrySet
().
stream
().
sorted
(
Map
.
Entry
.
comparingByKey
(
String
.
CASE_INSENSITIVE_ORDER
));
}
}
test/java/util/Map/EntryComparators.java
0 → 100644
浏览文件 @
83c573d4
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8009736 8010279
* @run testng EntryComparators
*/
import
java.util.function.Function
;
import
java.util.Comparator
;
import
java.util.AbstractMap
;
import
java.util.Map
;
import
org.testng.annotations.Test
;
import
static
org
.
testng
.
Assert
.
assertTrue
;
import
static
org
.
testng
.
Assert
.
fail
;
/**
* Unit tests for Map.Entry.comparing
*/
@Test
(
groups
=
"unit"
)
public
class
EntryComparators
{
private
<
K
,
V
>
void
assertPairComparison
(
K
k1
,
V
v1
,
K
k2
,
V
v2
,
Comparator
<
Map
.
Entry
<
K
,
V
>>
ck
,
Comparator
<
Map
.
Entry
<
K
,
V
>>
cv
)
{
final
Map
.
Entry
<
K
,
V
>
p11
=
new
AbstractMap
.
SimpleImmutableEntry
<>(
k1
,
v1
);
final
Map
.
Entry
<
K
,
V
>
p12
=
new
AbstractMap
.
SimpleImmutableEntry
<>(
k1
,
v2
);
final
Map
.
Entry
<
K
,
V
>
p21
=
new
AbstractMap
.
SimpleImmutableEntry
<>(
k2
,
v1
);
final
Map
.
Entry
<
K
,
V
>
p22
=
new
AbstractMap
.
SimpleImmutableEntry
<>(
k2
,
v2
);
assertTrue
(
ck
.
compare
(
p11
,
p11
)
==
0
);
assertTrue
(
ck
.
compare
(
p12
,
p11
)
==
0
);
assertTrue
(
ck
.
compare
(
p11
,
p12
)
==
0
);
assertTrue
(
ck
.
compare
(
p12
,
p22
)
<
0
);
assertTrue
(
ck
.
compare
(
p12
,
p21
)
<
0
);
assertTrue
(
ck
.
compare
(
p21
,
p11
)
>
0
);
assertTrue
(
ck
.
compare
(
p21
,
p12
)
>
0
);
assertTrue
(
cv
.
compare
(
p11
,
p11
)
==
0
);
assertTrue
(
cv
.
compare
(
p12
,
p11
)
>
0
);
assertTrue
(
cv
.
compare
(
p11
,
p12
)
<
0
);
assertTrue
(
cv
.
compare
(
p12
,
p22
)
==
0
);
assertTrue
(
cv
.
compare
(
p12
,
p21
)
>
0
);
assertTrue
(
cv
.
compare
(
p21
,
p11
)
==
0
);
assertTrue
(
cv
.
compare
(
p21
,
p12
)
<
0
);
Comparator
<
Map
.
Entry
<
K
,
V
>>
cmp
=
ck
.
thenComparing
(
cv
);
assertTrue
(
cmp
.
compare
(
p11
,
p11
)
==
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p11
)
>
0
);
assertTrue
(
cmp
.
compare
(
p11
,
p12
)
<
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p22
)
<
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p21
)
<
0
);
assertTrue
(
cmp
.
compare
(
p21
,
p11
)
>
0
);
assertTrue
(
cmp
.
compare
(
p21
,
p12
)
>
0
);
cmp
=
cv
.
thenComparing
(
ck
);
assertTrue
(
cmp
.
compare
(
p11
,
p11
)
==
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p11
)
>
0
);
assertTrue
(
cmp
.
compare
(
p11
,
p12
)
<
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p22
)
<
0
);
assertTrue
(
cmp
.
compare
(
p12
,
p21
)
>
0
);
assertTrue
(
cmp
.
compare
(
p21
,
p11
)
>
0
);
assertTrue
(
cmp
.
compare
(
p21
,
p12
)
<
0
);
}
public
void
testKVComparables
()
{
assertPairComparison
(
1
,
"ABC"
,
2
,
"XYZ"
,
Map
.
Entry
.<
Integer
,
String
>
comparingByKey
(),
Map
.
Entry
.<
Integer
,
String
>
comparingByValue
());
}
private
static
class
People
{
final
String
firstName
;
final
String
lastName
;
final
int
age
;
People
(
String
first
,
String
last
,
int
age
)
{
firstName
=
first
;
lastName
=
last
;
this
.
age
=
age
;
}
String
getFirstName
()
{
return
firstName
;
}
String
getLastName
()
{
return
lastName
;
}
int
getAge
()
{
return
age
;
}
}
private
final
People
people
[]
=
{
new
People
(
"John"
,
"Doe"
,
34
),
new
People
(
"Mary"
,
"Doe"
,
30
),
};
public
void
testKVComparators
()
{
// Comparator<People> cmp = Comparator.naturalOrder(); // Should fail to compiler as People is not comparable
// We can use simple comparator, but those have been tested above.
// Thus choose to do compose for some level of interation.
Comparator
<
People
>
cmp1
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getFirstName
);
Comparator
<
People
>
cmp2
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getLastName
);
Comparator
<
People
>
cmp
=
cmp1
.
thenComparing
(
cmp2
);
assertPairComparison
(
people
[
0
],
people
[
0
],
people
[
1
],
people
[
1
],
Map
.
Entry
.<
People
,
People
>
comparingByKey
(
cmp
),
Map
.
Entry
.<
People
,
People
>
comparingByValue
(
cmp
));
}
public
void
testNulls
()
{
try
{
Comparator
<
Map
.
Entry
<
String
,
String
>>
cmp
=
Map
.
Entry
.
comparingByKey
(
null
);
fail
(
"comparingByKey(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
try
{
Comparator
<
Map
.
Entry
<
String
,
String
>>
cmp
=
Map
.
Entry
.
comparingByValue
(
null
);
fail
(
"comparingByValue(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
}
test/java/util/function/BinaryOperator/BasicTest.java
0 → 100644
浏览文件 @
83c573d4
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8009736 8010279
* @run testng BasicTest
*/
import
java.util.Comparator
;
import
java.util.function.BinaryOperator
;
import
java.util.function.Function
;
import
java.util.function.ToIntFunction
;
import
org.testng.annotations.Test
;
import
static
java
.
util
.
function
.
BinaryOperator
.
minBy
;
import
static
java
.
util
.
function
.
BinaryOperator
.
maxBy
;
import
static
org
.
testng
.
Assert
.
assertSame
;
import
static
org
.
testng
.
Assert
.
fail
;
/**
* Unit tests for helper methods in Comparators
*/
@Test
(
groups
=
"unit"
)
public
class
BasicTest
{
private
static
class
People
{
final
String
firstName
;
final
String
lastName
;
final
int
age
;
People
(
String
first
,
String
last
,
int
age
)
{
firstName
=
first
;
lastName
=
last
;
this
.
age
=
age
;
}
String
getFirstName
()
{
return
firstName
;
}
String
getLastName
()
{
return
lastName
;
}
int
getAge
()
{
return
age
;
}
}
private
final
People
people
[]
=
{
new
People
(
"John"
,
"Doe"
,
34
),
new
People
(
"Mary"
,
"Doe"
,
30
),
};
public
void
testMaxBy
()
{
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getFirstName
);
// lesser
assertSame
(
maxBy
(
cmp
).
apply
(
people
[
0
],
people
[
1
]),
people
[
1
]);
// euqal
cmp
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getLastName
);
assertSame
(
maxBy
(
cmp
).
apply
(
people
[
0
],
people
[
1
]),
people
[
0
]);
// greater
cmp
=
Comparator
.
comparing
((
ToIntFunction
<
People
>)
People:
:
getAge
);
assertSame
(
maxBy
(
cmp
).
apply
(
people
[
0
],
people
[
1
]),
people
[
0
]);
}
public
void
testLesserOf
()
{
Comparator
<
People
>
cmp
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getFirstName
);
// lesser
assertSame
(
minBy
(
cmp
).
apply
(
people
[
0
],
people
[
1
]),
people
[
0
]);
// euqal
cmp
=
Comparator
.
comparing
((
Function
<
People
,
String
>)
People:
:
getLastName
);
assertSame
(
minBy
(
cmp
).
apply
(
people
[
0
],
people
[
1
]),
people
[
0
]);
// greater
cmp
=
Comparator
.
comparing
((
ToIntFunction
<
People
>)
People:
:
getAge
);
assertSame
(
minBy
(
cmp
).
apply
(
people
[
0
],
people
[
1
]),
people
[
1
]);
}
public
void
testNulls
()
{
try
{
BinaryOperator
<
String
>
op
=
minBy
(
null
);
fail
(
"minBy(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
try
{
BinaryOperator
<
String
>
op
=
maxBy
(
null
);
fail
(
"maxBy(null) should throw NPE"
);
}
catch
(
NullPointerException
npe
)
{}
}
}
test/java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java
浏览文件 @
83c573d4
...
@@ -22,7 +22,6 @@
...
@@ -22,7 +22,6 @@
*/
*/
package
org.openjdk.tests.java.util.stream
;
package
org.openjdk.tests.java.util.stream
;
import
java.util.Comparators
;
import
java.util.stream.LambdaTestHelpers
;
import
java.util.stream.LambdaTestHelpers
;
import
java.util.stream.OpTestCase
;
import
java.util.stream.OpTestCase
;
import
java.util.stream.StreamTestDataProvider
;
import
java.util.stream.StreamTestDataProvider
;
...
@@ -109,9 +108,9 @@ public class SequentialOpTest extends OpTestCase {
...
@@ -109,9 +108,9 @@ public class SequentialOpTest extends OpTestCase {
=
new
UnaryOperator
[]
{
=
new
UnaryOperator
[]
{
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
,
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
,
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
.
map
(
id
),
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
.
map
(
id
),
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
.
sorted
(
Comparator
s
.
naturalOrder
()),
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
.
sorted
(
Comparator
.
naturalOrder
()),
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
.
map
(
id
).
sorted
(
Comparator
s
.
naturalOrder
()).
map
(
id
),
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
.
map
(
id
).
sorted
(
Comparator
.
naturalOrder
()).
map
(
id
),
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
.
filter
(
LambdaTestHelpers
.
pEven
).
sorted
(
Comparator
s
.
naturalOrder
()).
map
(
id
),
(
UnaryOperator
<
Stream
<
Integer
>>)
s
->
s
.
filter
(
LambdaTestHelpers
.
pEven
).
sorted
(
Comparator
.
naturalOrder
()).
map
(
id
),
};
};
for
(
int
c1Index
=
0
;
c1Index
<
changers
.
length
;
c1Index
++)
{
for
(
int
c1Index
=
0
;
c1Index
<
changers
.
length
;
c1Index
++)
{
...
...
test/java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java
浏览文件 @
83c573d4
...
@@ -270,7 +270,7 @@ public class SliceOpTest extends OpTestCase {
...
@@ -270,7 +270,7 @@ public class SliceOpTest extends OpTestCase {
public
void
testLimitSort
()
{
public
void
testLimitSort
()
{
List
<
Integer
>
l
=
countTo
(
100
);
List
<
Integer
>
l
=
countTo
(
100
);
Collections
.
reverse
(
l
);
Collections
.
reverse
(
l
);
exerciseOps
(
l
,
s
->
s
.
limit
(
10
).
sorted
(
Comparator
s
.
naturalOrder
()));
exerciseOps
(
l
,
s
->
s
.
limit
(
10
).
sorted
(
Comparator
.
naturalOrder
()));
}
}
@Test
(
groups
=
{
"serialization-hostile"
})
@Test
(
groups
=
{
"serialization-hostile"
})
...
...
test/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java
浏览文件 @
83c573d4
...
@@ -40,10 +40,10 @@ public class SortedOpTest extends OpTestCase {
...
@@ -40,10 +40,10 @@ public class SortedOpTest extends OpTestCase {
public
void
testSorted
()
{
public
void
testSorted
()
{
assertCountSum
(
countTo
(
0
).
stream
().
sorted
(),
0
,
0
);
assertCountSum
(
countTo
(
0
).
stream
().
sorted
(),
0
,
0
);
assertCountSum
(
countTo
(
10
).
stream
().
sorted
(),
10
,
55
);
assertCountSum
(
countTo
(
10
).
stream
().
sorted
(),
10
,
55
);
assertCountSum
(
countTo
(
10
).
stream
().
sorted
(
cInteger
.
reverse
Order
()),
10
,
55
);
assertCountSum
(
countTo
(
10
).
stream
().
sorted
(
cInteger
.
reverse
d
()),
10
,
55
);
List
<
Integer
>
to10
=
countTo
(
10
);
List
<
Integer
>
to10
=
countTo
(
10
);
assertSorted
(
to10
.
stream
().
sorted
(
cInteger
.
reverse
Order
()).
iterator
(),
cInteger
.
reverseOrder
());
assertSorted
(
to10
.
stream
().
sorted
(
cInteger
.
reverse
d
()).
iterator
(),
cInteger
.
reversed
());
Collections
.
reverse
(
to10
);
Collections
.
reverse
(
to10
);
assertSorted
(
to10
.
stream
().
sorted
().
iterator
());
assertSorted
(
to10
.
stream
().
sorted
().
iterator
());
...
@@ -51,7 +51,7 @@ public class SortedOpTest extends OpTestCase {
...
@@ -51,7 +51,7 @@ public class SortedOpTest extends OpTestCase {
Spliterator
<
Integer
>
s
=
to10
.
stream
().
sorted
().
spliterator
();
Spliterator
<
Integer
>
s
=
to10
.
stream
().
sorted
().
spliterator
();
assertTrue
(
s
.
hasCharacteristics
(
Spliterator
.
SORTED
));
assertTrue
(
s
.
hasCharacteristics
(
Spliterator
.
SORTED
));
s
=
to10
.
stream
().
sorted
(
cInteger
.
reverse
Order
()).
spliterator
();
s
=
to10
.
stream
().
sorted
(
cInteger
.
reverse
d
()).
spliterator
();
assertFalse
(
s
.
hasCharacteristics
(
Spliterator
.
SORTED
));
assertFalse
(
s
.
hasCharacteristics
(
Spliterator
.
SORTED
));
}
}
...
@@ -87,8 +87,8 @@ public class SortedOpTest extends OpTestCase {
...
@@ -87,8 +87,8 @@ public class SortedOpTest extends OpTestCase {
assertSorted
(
result
.
iterator
());
assertSorted
(
result
.
iterator
());
assertContentsUnordered
(
data
,
result
);
assertContentsUnordered
(
data
,
result
);
result
=
exerciseOps
(
data
,
s
->
s
.
sorted
(
cInteger
.
reverse
Order
()));
result
=
exerciseOps
(
data
,
s
->
s
.
sorted
(
cInteger
.
reverse
d
()));
assertSorted
(
result
.
iterator
(),
cInteger
.
reverse
Order
());
assertSorted
(
result
.
iterator
(),
cInteger
.
reverse
d
());
assertContentsUnordered
(
data
,
result
);
assertContentsUnordered
(
data
,
result
);
}
}
...
@@ -104,23 +104,23 @@ public class SortedOpTest extends OpTestCase {
...
@@ -104,23 +104,23 @@ public class SortedOpTest extends OpTestCase {
assertContentsUnordered
(
data
,
result
);
assertContentsUnordered
(
data
,
result
);
result
=
withData
(
data
)
result
=
withData
(
data
)
.
stream
(
s
->
s
.
sorted
(
cInteger
.
reverse
Order
()).
sorted
(
cInteger
.
reverseOrder
()),
.
stream
(
s
->
s
.
sorted
(
cInteger
.
reverse
d
()).
sorted
(
cInteger
.
reversed
()),
new
CollectorOps
.
TestParallelSizedOp
<
Integer
>())
new
CollectorOps
.
TestParallelSizedOp
<
Integer
>())
.
exercise
();
.
exercise
();
assertSorted
(
result
,
cInteger
.
reverse
Order
());
assertSorted
(
result
,
cInteger
.
reverse
d
());
assertContentsUnordered
(
data
,
result
);
assertContentsUnordered
(
data
,
result
);
result
=
withData
(
data
)
result
=
withData
(
data
)
.
stream
(
s
->
s
.
sorted
().
sorted
(
cInteger
.
reverse
Order
()),
.
stream
(
s
->
s
.
sorted
().
sorted
(
cInteger
.
reverse
d
()),
new
CollectorOps
.
TestParallelSizedOp
<
Integer
>())
new
CollectorOps
.
TestParallelSizedOp
<
Integer
>())
.
exercise
();
.
exercise
();
assertSorted
(
result
,
cInteger
.
reverse
Order
());
assertSorted
(
result
,
cInteger
.
reverse
d
());
assertContentsUnordered
(
data
,
result
);
assertContentsUnordered
(
data
,
result
);
result
=
withData
(
data
)
result
=
withData
(
data
)
.
stream
(
s
->
s
.
sorted
(
cInteger
.
reverse
Order
()).
sorted
(),
.
stream
(
s
->
s
.
sorted
(
cInteger
.
reverse
d
()).
sorted
(),
new
CollectorOps
.
TestParallelSizedOp
<
Integer
>())
new
CollectorOps
.
TestParallelSizedOp
<
Integer
>())
.
exercise
();
.
exercise
();
...
...
test/sun/misc/JavaLangAccess/NewUnsafeString.java
浏览文件 @
83c573d4
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
*/
*/
import
java.util.Objects
;
import
java.util.Objects
;
import
java.util.Comparator
s
;
import
java.util.Comparator
;
import
sun.misc.JavaLangAccess
;
import
sun.misc.JavaLangAccess
;
import
sun.misc.SharedSecrets
;
import
sun.misc.SharedSecrets
;
...
@@ -48,7 +48,7 @@ public class NewUnsafeString {
...
@@ -48,7 +48,7 @@ public class NewUnsafeString {
if
(!
benchmark
.
equals
(
constructorCopy
))
{
if
(!
benchmark
.
equals
(
constructorCopy
))
{
throw
new
Error
(
"Copy not equal"
);
throw
new
Error
(
"Copy not equal"
);
}
}
if
(
0
!=
Objects
.
compare
(
benchmark
,
constructorCopy
,
Comparator
s
.
naturalOrder
()))
{
if
(
0
!=
Objects
.
compare
(
benchmark
,
constructorCopy
,
Comparator
.
naturalOrder
()))
{
throw
new
Error
(
"Copy not equal"
);
throw
new
Error
(
"Copy not equal"
);
}
}
...
@@ -58,7 +58,7 @@ public class NewUnsafeString {
...
@@ -58,7 +58,7 @@ public class NewUnsafeString {
if
(!
benchmark
.
equals
(
jlaCopy
))
{
if
(!
benchmark
.
equals
(
jlaCopy
))
{
throw
new
Error
(
"Copy not equal"
);
throw
new
Error
(
"Copy not equal"
);
}
}
if
(
0
!=
Objects
.
compare
(
benchmark
,
jlaCopy
,
Comparator
s
.
naturalOrder
()))
{
if
(
0
!=
Objects
.
compare
(
benchmark
,
jlaCopy
,
Comparator
.
naturalOrder
()))
{
throw
new
Error
(
"Copy not equal"
);
throw
new
Error
(
"Copy not equal"
);
}
}
...
@@ -68,7 +68,7 @@ public class NewUnsafeString {
...
@@ -68,7 +68,7 @@ public class NewUnsafeString {
if
(!
constructorCopy
.
equals
(
jlaCopy
))
{
if
(!
constructorCopy
.
equals
(
jlaCopy
))
{
throw
new
Error
(
"Copy not equal"
);
throw
new
Error
(
"Copy not equal"
);
}
}
if
(
0
!=
Objects
.
compare
(
constructorCopy
,
jlaCopy
,
Comparator
s
.
naturalOrder
()))
{
if
(
0
!=
Objects
.
compare
(
constructorCopy
,
jlaCopy
,
Comparator
.
naturalOrder
()))
{
throw
new
Error
(
"Copy not equal"
);
throw
new
Error
(
"Copy not equal"
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录