1、数组
数组属于引用类型数据,实质也是对象
动态初始化
先定义,然后new分配空间,接着再初始化赋值,举例:
int a[];
a = new int[3];
a[0] = 1;
a[1] = 2;
a[2] = 3;
静态初始化
定义的时候就赋值,举例:
int a[] = {1,2,3};
二维数组
定义举例:
int[][] a = {{1,2},{3,4}};
int[][] b = new int[2][];
在表格等情况下可能会用到,举例:
Object[] o1 = {"aaa", 18, "man"};
Object[] o2 = {"bbb", 22, "man"};
Object[] o3 = {"ccc", 20, "woman"};
Object[][] otable = new Object[3][];
otable[0] = o1;
otable[1] = o2;
otable[2] = o3;
for(Object[] o: otable)
System.out.println(Arrays.toString(o));
结果:
[aaa, 18, man]
[bbb, 22, man]
[ccc, 20, woman]
数组复制
使用System.arraycopy(原数组, 起始位置, 拷贝到的数组, 起始位置, 拷贝长度)
,举例:
int[] a = {1,2,3,4,5};
int[] b = {0,0,0,0,0};
System.arraycopy(a, 1, b, 1, 3);
System.out.println(Arrays.toString(b)); //[0, 2, 3, 4, 0]
举例:
String[] s = {"1", "2", "3"};
String[] p = new String[s.length];
System.arraycopy(s, 0, p, 0, s.length);
2、String
不可变类型序列,在java.lang
下的类,因此每个用""
包起来的都是String类的一个实例
charAt(index)
返回字符串第index个字符,举例:
String s = "abcde";
System.out.print(s.charAt(2)); //c
length()
字符串长度
indexOf(str[,start])
返回字符串出现str的第一个位置(没有返回-1),第二个可选参数代表开始索引位置,举例:
String s = "abcde";
System.out.print(s.indexOf("c")); //2
equals(str)
对于是否与str字符序列相等
equalsIgnoreCase(str)
忽略大小写后比较和str是否一样,举例:
String s = "abcde";
System.out.print(s.equalsIgnoreCase("ABCDE")); //true
replace(old, new)
替换单个字符,举例:
String s = "abcde";
System.out.println(s.replace('a', 's')); //bbcde
replaceAll(old, new)
替换字符串,举例:
String s = "abcde";
System.out.println(s.replaceAll("a", "bcd")); //bcdbcde
里面也可以通过匹配正则表达式来替换,举例:
String a = "abc123de";
System.out.println(a.replaceAll("\\d+", "aaa")); //abcaaade
startsWith(str)/endsWith(str)
是否以str开头/结尾
toUpperCase()/toLowerCase()
全部字符转大写/小写
substring(startIndex[,endIndex])
返回从startIndex到结尾的子序列,第二个参数可选,为到endIndex的子序列
trim()
去掉开头或者结尾空格后的字符串,相当于python的strip()
split(str)
按str分割字符串,举例:
String s = "abcde ";
System.out.print(s.split("a")[1]); //bcde
实际上应该是按正则表达式来分割字符串,举例:
System.out.println(Arrays.toString("sd2a3s".split("\\d"))); //[sd, a, s]
toCharArray()
转成char
字符数组,举例:
String a = "abcde";
for(char c: a.toCharArray())
System.err.println(c);
matches()
匹配正则表达式,符合则返回true
,否则返回false
,举例:
String a = "abcde";
System.out.println(a.matches("[a-z]+")); //true
getChars()/getBytes()
获得字符/字节数组
编码解码操作
使用getBytes(编码)
进行编码(需要抛出异常),使用String(byte, 编码)
进行解码,举例:
public static void main(String[] args) throws Exception{
String s = "你好";
byte[] b = s.getBytes("utf-8");
System.out.println(new String(b, "utf-8")); //你好
}
要注意的是编码和解码时必须使用统一编码,否则会造成乱码,此时则需要再按其解码的编码进行编码,然后再按正确的编码进行解码,举例:
public static void main(String[] args) throws Exception{
String s = "你好";
byte[] b = s.getBytes("utf-8");
String s1 = new String(b, "gbk");
System.out.println(s1); //浣犲ソ
byte[] b1 = s1.getBytes("gbk");
String s2 = new String(b1, "utf-8");
System.out.println(s2); //你好
}
3、容器API
Java提供了一个容器接口Collection(需要import java.util.*;
),其下关系:
-Collection(接口)
-Set(接口)
-HashSet(类)
-List(接口)
-LinkedList(类)
-ArrayList(类)
-Map(接口)
-HashMap(类)
其中定义也有有讲究的,比如:
Collection a = new ArrayList();
ArrayList a = new ArrayList();
上面两者的区别:前者到时候如果想转LinkedList时可以直接转,而后者不行
3.1 Collection
其下的类都有以下的通用接口
add(Object)
添加元素(里面填的是对象),例如:a.add(new Integer(123))
size()
列表长度
remove(Object)
清除某个对象(里面也都是对象)
contains(Object)
是否包含该元素
iterator()
在这些数据类型下都有一个iterator接口,即迭代器,其定义了下面三个方法:
boolean hasNext(); //判断游标右边是否还有元素
Object next(); //返回游标右边元素,并将游标往右移一位
void remove(); //删除游标左边的元素
实现了上面的方法后就可以使用迭代器了,举例:
Collection c = new HashSet();
c.add(new String("1"));
c.add(new String("2"));
c.add(new String("3"));
Iterator i = c.iterator();
while(i.hashNext()){
String a = i.next();
}
上面可以用for语句实现:
Collection c = new HashSet();
c.add(new String("1"));
c.add(new String("2"));
c.add(new String("3"));
for(Object i: c)
System.out.println(i);
isEmpty()
是否为空
clear()
清空容器中所有元素
toArray()
转化成Object数组
containsAll(Collection)
是否包含该容器的所有元素
addAll(Collection)
添加容器的所有元素
removeAll(Collection)
删除本容器和该容器都包含的元素
retainAll(Collection)
取本容器和该容器中都包含的元素
3.2 List
列表里面可以存放各种类型的元素对象(注意是对象),有序,相比数组除了存放对象可以随意外,其不像数组大小固定,可以动态扩容,但是速度比数组慢。在java.util.Collections
类下的List接口提供了常用方法如下
sort(List)
排序
reverse(List)
将原来的List倒过来,不是从大到小排序
shuffle(List)
随机排序
binarySearch(List, Object)
二分查找,第二个参数是要查找的对象,结果返回对象下标
copy(List1, List2)
将List2内容拷到List1
3.2.1 ArrayList
底层是数组实现的列表,查询效率高,增删效率低,线程不安全
3.2.2 LinkedList
和ArrayList相比,主要区别就是底层是链表实现的,因此查询效率低,增删效率高,线程也不安全
3.2.3 Vector
底层是数组实现的链表,相关的方法都加了同步检查(synchronized
标记),因此线程安全,但同时效率也会低一些,使用方法和前两个差不多
3.2.4常用方法
add(index, Object)
重写了方法,在第几个位置插入元素
set(index, Object)
修改第几个位置元素的值
get(index)
获取第几个位置元素的值
remove(index)
重写了方法,删除第几个位置的元素
indexOf(Object)
获取某个元素的下标(第一个),没有就-1
lastIndexOf(Object)
获取某个元素的下标(最后一个)
3.3 Map
Map接口提供了键值对存放的数据类型接口
3.3.1 HashMap
通过键值对标识,底层是由ArrayList+LinkedList结合而成的hash表(总体由多行ArrayList组成,每行内由LinkedList组成)实现,对于该数据结果判断是否内容相等,一般不用equals,用hashCode
来比较
3.3.2 TreeMap
底层是通过红黑二叉树来实现,效率一般低于HashMap,但是在排序Map的时候则会用到,即会根据Key值排序存储(底层继承了Comparable
接口,实现的public int compareTo(Object obj){}
方法是由Key排序)
3.3.3 HashTable
相比HashMap线程更安全,但是效率低,而且key和value不允许为空
3.3.4 常用方法
put(Object key, Object value)
添加键值对,本来添加的键值都必须是对象,但是在java1.5以后Map下支持自动将基础数据类型转成对象和对象转成基础数据(自动打包/解包机制),所以可以直接放基础数据,到时候会自动转成对象,举例:
Map m = new HashMap();
m.put("a", 1); //自动转成String和Integer对象
int a = (Integer)m.get("a");
System.out.println(a)
get(Object key)
获取键值对
keySet()
获取所有键名,举例循环输出所有值:
Map<String, String> m = new HashMap<String, String>();
m.put("aaa", "bbb");
m.put("bbb", "ccc");
for (String s : m.keySet()) {
System.out.println(m.get(s));
}
entrySet()
获取所有键值对的集合,返回的是Entry
对象,举例:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class test {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaa");
map.put(2, "bbb");
Set<Entry<Integer, String>> s = map.entrySet(); //返回Entry对象
for (Iterator<Entry<Integer, String>> iterator = s.iterator(); iterator
.hasNext();) {
Entry<Integer, String> entry = iterator.next();
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}
用迭代器比较繁琐,可以直接用for(x:XS)
方式输出,举例:
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaa");
map.put(2, "bbb");
for (Entry<Integer, String> m : map.entrySet()) {
System.out.println(m.getKey() + ":" + m.getValue());
}
}
values()
获取所有值
remove(Object key)
containsKey(Object key)
是否包含键
containsValue(Object Value)
是否包含值
size()
putAll(Map)
添加所有键值对
clear()
清空键值对
3.4 Set
集合接口,无序(即无法用下标索引),不可重复
3.4.1 HashSet
底层是基于HashMap实现,相当于一个简化版HashMap,因此查询和增删效率都较高,使用方法可以参考Collection
里的方法
3.4.2 TreeSet
底层是TreeMap实现的集合,所以结果会以从小到大排序
4、泛型
原来容器里的数据对象类型都是没有限制,因此基本都是接受Object,为了能够确定容器里存放的对象类型,引入了泛型,举例:
List<String> li = new ArrayList<String>();
这样所有的数据就都只能是String对象了,包括取数据时也可以使用泛型控制的迭代器,举例:
for(Iterator<String> it = li.interator(); it.hasNext(); )
{
String s = it.next();
System.out.println(s);
}
至于何时可以使用泛型,可以参考Api文档,当有<字符>
标识则说明可以使用,比如Map<K, V>
则说明键值都可以设置,所以就可以这样写:
Map<String, Integer> m = new hashMap<String, Integer>();
自定义泛型类
当自己写的类里假如需要一个泛型容器时,可以通过<字符>
(一般用T
/E
/K
/V
/?
,分别代表type
/element
/key
/value
/不确定类型,但其实啥都可以)来定义,此时该字符相当于一个形参,当实例化时设置泛型类后,该字符就是什么类,举例:
import java.util.Arrays;
public class test {
public static void main(String[] args) {
MyCollection<String> s = new MyCollection<String>(); // 设置了String的泛型,该对象里的T变成了String类
s.set("aaa", 0); // 第一个参数只能传String
System.out.println(s.toString());
}
}
class MyCollection<T> { // 代表泛型类的形参
Object[] o = new Object[5];
public void set(T t, int index) { // T即传入的泛型类
o[index] = t;
}
public String toString() {
return Arrays.toString(this.o);
}
}
网友评论