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.Setm.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 ...
随机推荐
- python_day11
一.简介 1.什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据. 2.关系型数据库 ...
- LOJ-10102(求A到B之间的割点)
题目链接:传送门 思路:求A到B之间必要的中间节点 条件:(1)只有一条路径经过中间节点:(low[B]>=num[u]&&num[v]<=num[B],没有从B到u的路径 ...
- ABP框架系列之十三:(Authorization-授权)
Introduction Almost all enterprise applications use authorization in some level. Authorization is us ...
- 后台获取url里面加密的参数中,特殊符号+获取到后端后是 一个空格的解决方法
进行加密,加密后的参数中有个+号: 前端的url:http://mtest.cmread.com:8145/nap/p/QRcode.jsp?activityId=11206&vcode=O/ ...
- 让用户输入一个日期字符串,将其转换成日期格式, 格式是(yyyy/MM/dd,yyyyMMdd,yyyy-MM-dd)中的一种, 任何一种转换成功都可以; 如果所有的都无法转换,输出日期格式非法。
第三种方法 while(true) { Date d; System.out.println("正在进行第一次匹配,请稍后~—~"); ...
- Makefile入门
相信大家对makefile都不陌生,在Linux下编写程序基本都离不开makefile的编写,我们都知道多个.c文件经过编译器编译后得到多个.o文件,这些文件是互相独立的,但最终我们要得到一个可正常运 ...
- XE下显示托盘图标(TrayIcon)
https://www.cnblogs.com/studypanp/p/4930619.html XE下显示托盘图标(TrayIcon) 1.拖一个TrayIcon控件 2.拖一个Applicat ...
- visual studio单项目一次生成多框架类库、多框架项目合并
目录 不同平台框架项目使用同一套代码,一次编译生成多个框架类库 需要先了解的东西 分析 添加PropertyGroup 多目标平台 编译符号和输出目录设置 添加依赖 代码文件处理 主副平台项目文件处理 ...
- liunx----配置搜狗输入法
话不多说直接看步骤 * 系统版本: ubuntu 18.04.1 // 查看命令为: # cat /etc/issue 1. 先查看当前系统是否存在 fcitx 框架: # dpkg -l | gre ...
- 使用 JSON-lib 出现异常 java.lang.reflect.InvocationTargetException
我是在使用json时引起的这个异常,上面是使用json-lib用到的几个jar包,原因是在commons-lang3-3.1.jar这个jar上,commons-lang3和commons-lang会 ...