Java字符串和容器
String
Java.lang.String
是Java的字符串类. Srting是一个不可变对象,所有对String修改的操作都需要构造新的String实例.
String可以由char数组或字符串字面值来构造:
char[] data = {'a', 'b', 'c'}
String s = new String(data)
String s = "Hello World";
String s = new String("Hello World");
使用+
运算符可以连接两个字符串:
String s = "Hello" + "World";
比较字符串
Java中的==
运算符用于比较两个引用是否指向了同一个对象:
String s1 = new String("Hello World");
String s2 = new String("Hello World");
System.out.println(s1 == s2); // false
上述程序输出为false
, 因为s1和s2指向了不同对象. 若要比较字符串内容是否相同, 请使用equals
方法:
String s1 = new String("Hello World");
String s2 = new String("Hello World");
System.out.println(s1.equals(s2)); // true
结果为true
没什么需要解释的. 下面这个代码的结果就比较有意思了:
String s1 = "Hello World";
String s2 = "Hello World";
System.out.println(s1 == s2); // true
结果为true, 说明s1和s2指向了同一个对象. Java在存储字符串字面值时, 会先检查内存中是否存在相同对象. 若存在就直接将新的引用指向该对象.
方法
我们常用format
方法以格式化的方式创建新字符串:
System.out.println(String.format("user:%s, age:%d", "abc", 12));
String提供了一系列方法:
s.charAt(int)
: 返回某个位置的字符, 下标从0开始s.length()
: 返回字符串的长度s.matches(String regex)
: 检查字符串时候符合正则表达式regex定义的模式, 返回boolean.
"A123".matches("[a-zA-Z][0-9]*");
s.substring(int start, int end)
: 返回[start, end)范围内的子串, 若省略end则返回剩余全部字符串.
"HelloWorld".substring(5, 7); //Wo
HelloWorld".substring(5); //World
类型转换
s.getBytes()
: 转换为bytes[]
s.toCharArray()
: 转换为char[]
Integer.parseInt(s)
: 转换为intDouble.parseDouble(s)
: 转换为double
StringBuffer 与 StringBuilder
java.lang.StringBuffer
与java.lang.StringBuilder
是可变的字符串对象.
StringBuilder较快但是线程不安全的, 在对线程安全没有要求时我们通常使用StringBuilder.
它们拥有和String类似的方法, 并提供了动态操作的API:
sb.append(String)
: 将字符串追加到末尾.sb.reverse()
: 字符串反向sb.delete(start, end)
: 删除[start, end)范围内的字符sb.insert(i, seq)
: 将字符序列插入i位置sb.replace(start, end, str)
: 用str替换[start, end)处的字串
Array
Java对所有数据类型都提供了内置的数组支持. 数组是定长的, 下标从0开始.
数组有两种声明方式:
int[] arr = new int[5];
不建议使用下面这种方式:
int arr[] = new int[5];
也可以直接使用数组字面值:
int[] arr = {1, 2, 3};
length()
方法用于获取长度, []
运算符可以访问或修改某个元素:
arr[0] = 2;
i = arr[1];
Java很容易实现多维数组:
int[][] mat = new int[5][5];
mat[2][2] = 1;
java.util.Arrays
提供了一些操作数组的工具:
Arrays.fill(arr, val)
: 将数组arr中所有元素设为valArrays.binarySearch(arr, key)
: 在数组arr用二分法查找元素key, arr必须已经排好序. 找到返回索引, 否则返回-1.Arrays.equals(arr1, arr2)
: 判断arr1和arr2中的内容是否相同Arrays.sort(arr)
: 对数组进行升序排序.
foreach可以用于遍历数组:
int[] arr = {1, 2, 3};
for (int i : arr) {
System.out.println(i);
}
List
Java Collection框架提供了各种容器的借口和实现, 所有容器类均采用泛型实现. 所有类均实现了iterable接口, 可以使用for-each遍历.
java.util.list
是线性容器的interface, Java中提供了三种常用的实现:
java.util.ArrayList
: 使用数组实现, 线程不安全java.util.LinkedList
: 使用链表实现, 线程不安全java.util.vector
: 线程安全实现
注意不能使用内置类型初始化, 必须使用封装类:
List<Integer> l = new ArrayList<Integer>(5);
list
接口声明了以下方法:
l.get(i)
: 返回指定位置的元素, 下标从0开始l.set(i, val)
: 设置指定位置的元素l.size()
: 返回容器中元素的个数l.contains(e)
: 判断容器中是否包含指定元素val, 返回boolean值.l.equals(c)
: 判断容器相同位置上的元素是否相同, 返回boolean值l.add(i, e)
: 在指定位置插入元素val, 若省略i则在末尾插入l.addAll(i, c)
: 在指定位置插入容器c中所有元素, 若省略i则在末尾插入l.remove(i)
: 删除指定位置上的元素l.clear()
: 删除所有元素l.clone()
: 返回自身的浅拷贝副本l.toArray()
: 转换为相应类型的数组
list
同样可以用foreach遍历:
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
for (String s : list) {
System.out.println(s);
}
Set
java.util.Set
是无序的, 不允许重复的容器接口, 对应数学上的集合. Java提供了HashSet
和TreeSet
两种实现.
Set<String> s = new HashSet<String>();
Set
接口声明了下列方法:
s.contians(e)
: 判断容器中是否包含元素e, 返回boolean值s.equals(c)
: 判断两个容器中包含的元素是否完全相同, 返回boolean值l.size()
: 返回容器中元素的个数l.add(e)
: 添加元素vall.addAll(c)
: 添加容器c中所有元素l.remove(e)
: 删除指定的元素l.clear()
: 删除所有元素l.clone()
: 返回自身的浅拷贝副本l.toArray()
: 转换为相应类型的数组
foreach遍历集合:
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
for (String s : set) {
System.out.println(s);
}
Map
java.util.Map
是保存键值对的容器, 键不允许重复. Java提供了HashMap
和TreeMap
两种实现.
Map<String, Integer> m = new HashMap<String, Integer>();
Map
接口声明了下列方法:
m.containsKey(key)
: 判断所有键中是否包含key, 返回boolean值m.containsValue(val)
: 判断所有值中是否包含val, 返回boolean值m.get(key)
: 返回key对应的值m.put(key, val)
: 设置key对应的值为val, 若不存则新建m.putAll(map)
: 加入map中所有键值对, 重复的进行覆盖m.remove(key)
: 删除指定键值对m.clear()
: 删除所有键值对m.keySet()
: 返回所有键组成的java.util.Set
m.values()
: 返回所有值组成的java.util.Collection
遍历Map需要Entry的帮助:
Map<String, String> map = new HashMap<>();
map.put("a", "1");
map.put("b", "2");
map.put("c", "3");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
Iterator
java.util.Iterator
定义了迭代器接口, 在使用迭代器遍历容器时不需要了解容器的具体数据结构.
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
Iterator<String> iter = list.iterator();
while(iter.hasNext()) {
String str = iter.next();
System.out.println(str);
}
iter.next()
方法会返回游标指向的元素, 并将游标后移一位. iter.hasNext()
用于检测是否完成了遍历.
iter.remove()
方法可以删除迭代器上一次返回的元素, 通常迭代器无法添加元素.
迭代器由ArrayList
等实现类提供, 上文提及的foreach遍历实际上是通过容器的迭代器实现的.
Set
容器的迭代器示例:
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
Iterator<String> iter = set.iterator();
while(iter.hasNext()) {
String str = iter.next();
System.out.println(str);
}
Map
容器的迭代器同样依赖于EntrySet
:
Map<String, String> map = new HashMap<>();
map.put("a", "1");
map.put("b", "2");
map.put("c", "3");
Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
System.out.println(entry.getKey() + ":" + entry.getValue());
}
ListIterator
List
接口除了iterator()
外还提供了功能更强的listIterator()
. listIterator()
拥有iterator()
的全部功能, 并且可以双向遍历和添加元素.
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
ListIterator<String> iter = list.listIterator();
while(iter.hasNext()) {
String str = iter.next();
System.out.println(str);
}
iter.add("d");
while(iter.hasPrevious()) {
String str = iter.previous();
System.out.println(str);
}
fail-fast && fail-safe
Collections
框架中的常规容器使用fail-fast迭代器, 如ArrayList
和HashMap
并发容器通常使用fail-safe迭代器.
fail-fast迭代器会记录容器发生结构性改变(添加删除元素)的次数, 若迭代过程中容器发生了结构性改变fail-fast迭代器会抛出运行时异常终止迭代.
迭代过程中的结构性改变通常是由于其它线程修改了容器, 终止迭代可以避免出现不一致的错误.
CopyOnWriteArrayList
和ConcurrentHashMap
等并发容器则使用fail-safe迭代器, fail-safe迭代器在容器的快照(snapshot)上进行遍历. 容器发生结构性改变时快照不受影响, fail-safe迭代器可以正常完成遍历.
相对于只提供访问接口不存储数据的fail-fast迭代器, fail-safe迭代器需要复制集合快照,产生较大开销. fail-safe迭代器基于快照的访问方式虽然可以在并发环境下正常遍历, 但无法保证访问到最新数据.
本文只对fail-fast与fail-safe迭代器进行简单介绍, 在各容器的源码解析中将进一步介绍迭代器的实现.
enum
Java使用enum关键字来定义枚举:
enum Season {
Spring, Summer, Autum, Winter;
}
public class Main {
public static void main(String[] args) {
System.out.println(Season.Spring); // print: Spring
}
}
enum
关键字与class
关键字的地位相同, enum
也可以定义其它属性和方法.
enum
中的每个枚举值类似于一个实例, 我们可以在enum
中为其定义构造方法.
enum Season {
Spring(2, 4), Summer(5, 7), Autum(8, 10), Winter(11, 1);
public int start;
public int stop;
private Season(int start, int stop) {
this.start = start;
this.stop = stop;
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Season.Spring); // Spring
System.out.println(Season.Spring.start); // 2
}
}
注意, enum
的构造器只能是私有的(private).
BitSet
java.util.BitSet
是位的容器, 我们可以用它保存标志位等数据:
BitSet bs = new BitSet(5);
BitSet提供了一些方法用于操作:
bs.get(i)
: 以boolean的形式返回第i位, 下标从0开始bs.get(start, end)
: 以BitSet的形式返回[start, end)中的字节.bs.set(i, b)
: 将第i位设为布尔值b, 省略b时设为true.bs.equals(c)
: 判断与容器c内容是否相同bs.clear()
: 将所有位设为falsebs.size()
: 返回总位数bs1.and(bs2)
: 进行位与运算, 返回BitSetbs1.andNot(bs2)
: 进行位与非运算, 返回BitSetbs1.or(bs2)
: 进行位或运算, 返回BitSetbs1.xor(bs2)
: 进行位异或运算, 返回BitSet
Java字符串和容器的更多相关文章
- 为什么Java字符串是不可变对象?
转自 http://developer.51cto.com/art/201503/468905.htm 本文主要来介绍一下Java中的不可变对象,以及Java中String类的不可变性,那么为什么Ja ...
- Java字符串String
Java字符串String 我们知道Java的字符窜是Immutable(不可变)的,一旦创建就不能更改其内容了:平常我们对字符串的操作是最多的,其实对字符串的操作,返回的字符串都是新建的字符串对象, ...
- java字符串集合
一,java的接口跟C语言所能做到的相比确实是让人眼前一亮的东西.利用接口可以将多种东西放到一起,在编程过程中就能省略掉相同类的很多重复代码,将代码进行分类别的,统一的处理. 二,java中的字符串处 ...
- Java字符串String 集合的迭代器
Java字符串String 我们知道Java的字符窜是Immutable(不可变)的,一旦创建就不能更改其内容了:平常我们对字符串的操作是最多的,其实对字符串的操作,返回的字符串都是新建的字符串对象, ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Java多线程-并发容器
Java多线程-并发容器 在Java1.5之后,通过几个并发容器类来改进同步容器类,同步容器类是通过将容器的状态串行访问,从而实现它们的线程安全的,这样做会消弱了并发性,当多个线程并发的竞争容器锁的时 ...
- (转)Java字符串
转自:http://blog.sina.com.cn/s/blog_899678b90101brz0.html 创建字符串有两种方式:两种内存区域(字符串池,堆)1," " 引号创 ...
- 转:java多线程--同步容器
java同步容器 在Java的集合容器框架中,主要有四大类别:List.Set.Queue.Map.List.Set.Queue接口分别继承了Collection接口,Map本身是一个接口.注意Col ...
- Java字符串split函数的注意事项
Java字符串的split方法可以分割字符串,但和其他语言不太一样,split方法的参数不是单个字符,而是正则表达式,如果输入了竖线(|)这样的字符作为分割字符串,会出现意想不到的结果, 如, Str ...
随机推荐
- Codeforces 835C-Star sky
题目链接:http://codeforces.com/problemset/problem/835/C 题意:天上有很多星星,每个星星有他自己的坐标和初始亮度,然后每个星星的亮度在一秒内会加一如果大于 ...
- hadoop启动
安装完hadoop集群之后,第一次启动之前必须初始化,之后就可以不用再初始化(注意:初始化操作只可以一次) hdfs namenode -format (hadoop namenode -format ...
- 常见bat(批处理)命令的语法规则
最近由于在做cocos2d的项目,需要用到一些bat命令,在此做些记录. bat命令用txt文本编辑就行,编辑完之后将后缀名改为bat即可运行.先来一个最简单的例子: @echo off echo \ ...
- 14. The Realities of Telecommuting 远程办公的现状
14. The Realities of Telecommuting 远程办公的现状 (1) Telecommuting——substituting the computer for the trip ...
- centos7配置Hadoop集群环境
参考: https://blog.csdn.net/pucao_cug/article/details/71698903 设置免密登陆后,必须重启ssh服务 systermctl restart ss ...
- ubuntu服务器搭建DVWA站点
把DVWA里面的文件夹拷贝到/var/www/html里面去 1.安装之前先更新系统 sudo apt update 2.安装Apache2 sudo apt install apache2 3.安装 ...
- Python PEP 8 编码规范中文版
原文链接:http://legacy.python.org/dev/peps/pep-0008/ 转发链接:https://blog.csdn.net/ratsniper/article/detail ...
- hdu 4027 Can you answer these queries?[线段树]
题目 题意: 输入一个 :n .(1<=n<<100000) 输入n个数 (num<2^63) 输入一个m :代表m个操作 (1<=m<<100 ...
- 物体检测,Error: maximum box coordinate value is too large
使用ssd目标检测,出现error:maximum box coordinate value is larger than 1.100000: ] [1.325] 主要原因在于,用labelImg 标 ...
- 测试工具之Jmeter(各部件简单介绍)
jmeter可以到官网下载: http://jakarta.apache.org/ 下载后解压即可使用,双击如下文件打开Jmeter界面: $JMETER_HOME\apache-jmeter-3.1 ...