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);
}
}










网友评论