Path: blob/master/src/java.base/share/classes/java/lang/CharSequence.java
41152 views
/*1* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.lang;2627import java.util.NoSuchElementException;28import java.util.Objects;29import java.util.PrimitiveIterator;30import java.util.Spliterator;31import java.util.Spliterators;32import java.util.function.IntConsumer;33import java.util.stream.IntStream;34import java.util.stream.StreamSupport;3536/**37* A {@code CharSequence} is a readable sequence of {@code char} values. This38* interface provides uniform, read-only access to many different kinds of39* {@code char} sequences.40* A {@code char} value represents a character in the <i>Basic41* Multilingual Plane (BMP)</i> or a surrogate. Refer to <a42* href="Character.html#unicode">Unicode Character Representation</a> for details.43*44* <p> This interface does not refine the general contracts of the {@link45* java.lang.Object#equals(java.lang.Object) equals} and {@link46* java.lang.Object#hashCode() hashCode} methods. The result of testing two objects47* that implement {@code CharSequence} for equality is therefore, in general, undefined.48* Each object may be implemented by a different class, and there49* is no guarantee that each class will be capable of testing its instances50* for equality with those of the other. It is therefore inappropriate to use51* arbitrary {@code CharSequence} instances as elements in a set or as keys in52* a map. </p>53*54* @author Mike McCloskey55* @since 1.456*/5758public interface CharSequence {5960/**61* Returns the length of this character sequence. The length is the number62* of 16-bit {@code char}s in the sequence.63*64* @return the number of {@code char}s in this sequence65*/66int length();6768/**69* Returns the {@code char} value at the specified index. An index ranges from zero70* to {@code length() - 1}. The first {@code char} value of the sequence is at71* index zero, the next at index one, and so on, as for array72* indexing.73*74* <p>If the {@code char} value specified by the index is a75* <a href="{@docRoot}/java.base/java/lang/Character.html#unicode">surrogate</a>, the surrogate76* value is returned.77*78* @param index the index of the {@code char} value to be returned79*80* @return the specified {@code char} value81*82* @throws IndexOutOfBoundsException83* if the {@code index} argument is negative or not less than84* {@code length()}85*/86char charAt(int index);8788/**89* Returns {@code true} if this character sequence is empty.90*91* @implSpec92* The default implementation returns the result of calling {@code length() == 0}.93*94* @return {@code true} if {@link #length()} is {@code 0}, otherwise95* {@code false}96*97* @since 1598*/99default boolean isEmpty() {100return this.length() == 0;101}102103/**104* Returns a {@code CharSequence} that is a subsequence of this sequence.105* The subsequence starts with the {@code char} value at the specified index and106* ends with the {@code char} value at index {@code end - 1}. The length107* (in {@code char}s) of the108* returned sequence is {@code end - start}, so if {@code start == end}109* then an empty sequence is returned.110*111* @param start the start index, inclusive112* @param end the end index, exclusive113*114* @return the specified subsequence115*116* @throws IndexOutOfBoundsException117* if {@code start} or {@code end} are negative,118* if {@code end} is greater than {@code length()},119* or if {@code start} is greater than {@code end}120*/121CharSequence subSequence(int start, int end);122123/**124* Returns a string containing the characters in this sequence in the same125* order as this sequence. The length of the string will be the length of126* this sequence.127*128* @return a string consisting of exactly this sequence of characters129*/130public String toString();131132/**133* Returns a stream of {@code int} zero-extending the {@code char} values134* from this sequence. Any char which maps to a <a135* href="{@docRoot}/java.base/java/lang/Character.html#unicode">surrogate code136* point</a> is passed through uninterpreted.137*138* <p>The stream binds to this sequence when the terminal stream operation139* commences (specifically, for mutable sequences the spliterator for the140* stream is <a href="../util/Spliterator.html#binding"><em>late-binding</em></a>).141* If the sequence is modified during that operation then the result is142* undefined.143*144* @return an IntStream of char values from this sequence145* @since 1.8146*/147public default IntStream chars() {148class CharIterator implements PrimitiveIterator.OfInt {149int cur = 0;150151public boolean hasNext() {152return cur < length();153}154155public int nextInt() {156if (hasNext()) {157return charAt(cur++);158} else {159throw new NoSuchElementException();160}161}162163@Override164public void forEachRemaining(IntConsumer block) {165for (; cur < length(); cur++) {166block.accept(charAt(cur));167}168}169}170171return StreamSupport.intStream(() ->172Spliterators.spliterator(173new CharIterator(),174length(),175Spliterator.ORDERED),176Spliterator.SUBSIZED | Spliterator.SIZED | Spliterator.ORDERED,177false);178}179180/**181* Returns a stream of code point values from this sequence. Any surrogate182* pairs encountered in the sequence are combined as if by {@linkplain183* Character#toCodePoint Character.toCodePoint} and the result is passed184* to the stream. Any other code units, including ordinary BMP characters,185* unpaired surrogates, and undefined code units, are zero-extended to186* {@code int} values which are then passed to the stream.187*188* <p>The stream binds to this sequence when the terminal stream operation189* commences (specifically, for mutable sequences the spliterator for the190* stream is <a href="../util/Spliterator.html#binding"><em>late-binding</em></a>).191* If the sequence is modified during that operation then the result is192* undefined.193*194* @return an IntStream of Unicode code points from this sequence195* @since 1.8196*/197public default IntStream codePoints() {198class CodePointIterator implements PrimitiveIterator.OfInt {199int cur = 0;200201@Override202public void forEachRemaining(IntConsumer block) {203final int length = length();204int i = cur;205try {206while (i < length) {207char c1 = charAt(i++);208if (!Character.isHighSurrogate(c1) || i >= length) {209block.accept(c1);210} else {211char c2 = charAt(i);212if (Character.isLowSurrogate(c2)) {213i++;214block.accept(Character.toCodePoint(c1, c2));215} else {216block.accept(c1);217}218}219}220} finally {221cur = i;222}223}224225public boolean hasNext() {226return cur < length();227}228229public int nextInt() {230final int length = length();231232if (cur >= length) {233throw new NoSuchElementException();234}235char c1 = charAt(cur++);236if (Character.isHighSurrogate(c1) && cur < length) {237char c2 = charAt(cur);238if (Character.isLowSurrogate(c2)) {239cur++;240return Character.toCodePoint(c1, c2);241}242}243return c1;244}245}246247return StreamSupport.intStream(() ->248Spliterators.spliteratorUnknownSize(249new CodePointIterator(),250Spliterator.ORDERED),251Spliterator.ORDERED,252false);253}254255/**256* Compares two {@code CharSequence} instances lexicographically. Returns a257* negative value, zero, or a positive value if the first sequence is lexicographically258* less than, equal to, or greater than the second, respectively.259*260* <p>261* The lexicographical ordering of {@code CharSequence} is defined as follows.262* Consider a {@code CharSequence} <i>cs</i> of length <i>len</i> to be a263* sequence of char values, <i>cs[0]</i> to <i>cs[len-1]</i>. Suppose <i>k</i>264* is the lowest index at which the corresponding char values from each sequence265* differ. The lexicographic ordering of the sequences is determined by a numeric266* comparison of the char values <i>cs1[k]</i> with <i>cs2[k]</i>. If there is267* no such index <i>k</i>, the shorter sequence is considered lexicographically268* less than the other. If the sequences have the same length, the sequences are269* considered lexicographically equal.270*271*272* @param cs1 the first {@code CharSequence}273* @param cs2 the second {@code CharSequence}274*275* @return the value {@code 0} if the two {@code CharSequence} are equal;276* a negative integer if the first {@code CharSequence}277* is lexicographically less than the second; or a278* positive integer if the first {@code CharSequence} is279* lexicographically greater than the second.280*281* @since 11282*/283@SuppressWarnings("unchecked")284public static int compare(CharSequence cs1, CharSequence cs2) {285if (Objects.requireNonNull(cs1) == Objects.requireNonNull(cs2)) {286return 0;287}288289if (cs1.getClass() == cs2.getClass() && cs1 instanceof Comparable) {290return ((Comparable<Object>) cs1).compareTo(cs2);291}292293for (int i = 0, len = Math.min(cs1.length(), cs2.length()); i < len; i++) {294char a = cs1.charAt(i);295char b = cs2.charAt(i);296if (a != b) {297return a - b;298}299}300301return cs1.length() - cs2.length();302}303304}305306307