数组就是一种容器,可以在其中放置对象或基本类型数据。
数组的优势:一种简单的线性序列,效率高,就是不灵活,容量需要事先定义好,不能随着需求的变化而扩容
1、泛型概念
泛型是jdk1.5以后增加的,可以帮助我们建立类型安全的集合。
泛型的本质就是“数据类型的参数化”,我们可以把泛型理解为数据类型的一个占位符(形式参数),即告诉编译器,在调用泛型时必须传入时间类型。
自定义泛型
我们 可以在类的声明出增加泛型列表,如<T,E,V>
字符可以是任何标识符,一般采用这3个字母。
class MyCollection<E>{//E表示泛型
Object[] objs=new Object[5];
public E get(int index){
return (E) objs[index];
}
public void set(E e,int index){
objs[index] =e;
}
}
E代表占位符,表示传入的类型
public class Test2 {
public static void main(String[] args) {
MyCollection<String> mc=new MyCollection<String>();
mc.set("aaa",0);
mc.set("111",1);
String b=mc.get(1);
System.out.println(b);
}
}
class MyCollection<E>{//E表示泛型
Object[] objs=new Object[5];
public E get(int index){
return (E) objs[index];
}
public void set(E e,int index){
objs[index] =e;
}
}
容器中使用泛型
容器相关类型都定义了泛型,我们在开发和工作中,在使用容器时都要使用泛型,这样,容器的存储数据、读取数据时都避免了大量的类型判断,非常便捷。
泛型类的在集合中的使用
public static void main(String[] args) {
//以下代码中List、Set、Map、Iterator都是与容器相关的接口
List<String> lis=new ArrayList<String>();
Set<Man> mans=new HashSet<Man>();
Map<Integer,Man> maps=new HashMap<Integer, Man>();
Iterator<Man> iterator=mans.iterator();
}
2、collection接口
collection表示一组对象,它是集中、收集的意思。Collection接口的两个子接口是List、Set接口。
常用方法
方法 | 说明 |
---|---|
boolean add(Object obj) | 添加一个元素 |
boolean addAll(Collection c) | 添加一个集合的元素 |
void clear() | 移除所有元素 |
boolean remove(Object o) | 移除一个元素 |
boolean removeAll(Collection c) | 移除一个集合的元素(是一个还是所有) |
boolean contains(Object o) | 判断集合中是否包含指定的元素 |
boolean containsAll(Collection c) | 判断集合中是否包含指定的集合元素(是一个还是所有) |
boolean isEmpty() | 判断集合是否为空 |
int size() | 元素的个数 |
boolean retainAll(Collection c) | 两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢? |
Object[] toArray() | 把集合转换为数组 |
Iterator iterator() | 获取迭代器,用于遍历所有元素 |
public class Test2 {
public static void main(String[] args) {
Collection c=new ArrayList<>();
c.add("aaa");
c.add("bbb");
c.addAll(c);
System.out.println(c);
c.remove("aaa");
System.out.println(c);
if(c.contains("aaa")){
System.out.println("数组包含aaa");
}
if(c.contains("bbb")){
System.out.println("数组包含bbb");
}
System.out.println("数组的个数是"+c.size());
}
}
3、List接口
List是有序、可重复的容器
List接口常用的实现类有3个:ArrayList、LinkedList和Vector。
除了collection接口中的方法,List多了一些顺序(索引)有关的方法
方法 | 说明 |
---|---|
void add(int index,Object element) | 在指定位置插入元素,以前元素全部后移一位 |
Object set(int index,Object element) | 修改指定位置的元素 |
Object get(int index) | 返回指定位置的元素 |
Object remove | 删除指定位置的元素,后面元素往前移动 |
int indexOf(Object o) | 返回第一个匹配元素的索引,如果没有该元素,则返回-1 |
int lastIndexOf(Object o) | 返回最后一个匹配元素的索引,如果没有该元素,则返回-1 |
A:ArrayList,底层采用数组结构的实现的。(内存中连续空间)。jdk1.2
只实现了List接口,功能都是List接口中规定的。
优缺点:
优点:遍历访问元素,效率很高
缺点:插入或删除元素,效率相对低。
B:LinkedList,底层采用双向链表结构实现的。(元素在内存中不挨着,元素之间的指向)。jdk1.2
实现了List接口的同时,还实现了Deque接口,所以有这两个接口中的功能。
优缺点:
优点:插入或删除元素,效率很高。
缺点:遍历访问元素,效率相对低。
注意点:
如果一个集合,频繁的添加或删除元素,建议选择LinkedList。
如果一个集合,绝大多数的操作就是遍历查询,建议选择ArrayList。
如果要模拟栈,队列等结构,建议选择LinkedList。
C:Vector,是ArrayList的前身。也是数组的结构。古老的类。从jdk1.0的版本就有了。
线程安全,效率低,后来被ArrayList替代了。
ArrayList和LinkedList都是线程不安全的,效率高。Collections工具类,可以获取线程安全的集合。
public class Test2 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add(1,"eee");
System.out.println(list);
list.set(0,"arr");
System.out.println(list);
System.out.println(list.get(2));
list.remove(1);
System.out.println(list);
System.out.println(list.indexOf("ccc"));
}
}
数组长度是有限的,而ArrayList是可以存放任意数量的对象,长度不受限制。
4、Map接口
Map就是用来存储“键(key)----值(value)”对的。通过键来标识,所以键不能重复
Map接口的实现类有HashMap、TreeMap、HashTable、Properties等。
方法 | 说明 |
---|---|
Object put(key,value) | 存放键值对 |
Object get(key) | 通过键对象查找得到值对象 |
Object remove(Object key) | 删除键对象对应的键值对 |
boolean containsKey(Object key) | Map容器中是否包含键对象 |
boolean containsValue(Object value) | Map容器中是否包含值对象 |
int size() | 包含键值对的数量 |
boolean isEmpty() | Map是否为空 |
void putAll(Map m) | 将m所有键值对存放到本map对象 |
void clear() | 清空本map对象所有键值对 |
public class Test2 {
public static void main(String[] args) {
Map map=new HashMap();
map.put("name","kk");
map.put("age","18");
System.out.println(map.get("age"));
map.remove("name");
System.out.println(map);
if(map.containsKey("age")){
System.out.println("包含了age");
}
map.put("addr","福州");
System.out.println(map.size());
if(!map.isEmpty()){
System.out.println("map不为空");
}else {
System.out.println("map为空");
}
}
}
//可以使用泛型
Map<Integer,String> map=new HashMap<>();
注意:map中key是不能重复
public class Test2 {
public static void main(String[] args) {
Employee e1=new Employee(10001,"高娜",5000);
Employee e2=new Employee(10005,"高键",6000);
Map<Integer,Employee> map=new HashMap<>();
map.put(1001,e1);
map.put(1002,e2);
System.out.println(map);
}
}
class Employee{
private int id;
private String ename;
private double aslary;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public double getAslary() {
return aslary;
}
public void setAslary(double aslary) {
this.aslary = aslary;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", ename='" + ename + '\'' +
", aslary=" + aslary +
'}';
}
public Employee(int id, String ename, double aslary) {
this.id = id;
this.ename = ename;
this.aslary = aslary;
}
}
其中的Entry[] table 就是HashMap的核心数组结构,我们也称为“位桶数组”。
5、Set接口
set接口继承自collection,set接口中没有新增方法,方法和collection保持完全一致。我们在前面通过List学习的方法,在set中仍然适用。
set容器的特点:无序,不可重复。无序指的是set的元素没有索引,我们只能遍历不能查找。
set常用实现类有:hashset、Treeset等,我们一般使用hashset。
6、迭代器的使用-List、Set和Map
迭代器遍历list/set
public class Test2 {
public static void main(String[] args) {
//Set<String> list=new HashSet<>();
List<String> list=new ArrayList<>();
for(int i=0;i<5;i++){
list.add("a"+i);
}
System.out.println(list);
//获取迭代对象并进行遍历
for(Iterator<String> iter=list.iterator();iter.hasNext();){
String temp=iter.next();
System.out.println(temp);
//删除3结尾的字符串
if(temp.endsWith("3")){
iter.remove();
}
System.out.println(list);
}
}
}
遍历Map
public class Test2 {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap<>();
for(int i=0;i<5;i++){
map.put(i,"a"+i);
}
System.out.println(map);
Set<Map.Entry<Integer,String>> ss=map.entrySet();
//获取迭代对象并进行遍历
for(Iterator<Map.Entry<Integer,String>> iter=ss.iterator();iter.hasNext();){
Map.Entry<Integer,String> temp=iter.next();
System.out.println(temp);
}
}
}
我们也可以通过map的keySet()、valueSet()获取key和value的集合,从而遍历它们。
public class Test2 {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap<>();
for(int i=0;i<5;i++){
map.put(i,"a"+i);
}
System.out.println(map);
Set<Integer> ss=map.keySet();
for(Iterator<Integer> itr=ss.iterator();itr.hasNext();){
Integer key=itr.next();
System.out.println(key+"---"+map.get(key));
}
}
}
7、collections工具类
类java.util.collections提供了一个操作Set、List和Map等集合的工具类,该工具类里面提供了大量方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象实现同步控制等方法。
方法 | 说明 |
---|---|
Reverse(List list) | 反转指定列表中元素的顺序 |
Shuffle(List list) | 使用默认随机源对指定列表进行置换 |
Sort(List list) | 根据指定比较器产生的顺序对指定列表进行排序 |
Sort(list list,Comparator c) | 根据指定比较器产生的顺序对指定列表进行排序 |
Swap(List list,int distance) | 根据指定的距离轮换指定列表中的元素 |
public class Test2 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
for(int i=0;i<5;i++){
list.add("a"+i);
}
list.set(1,"a99");
System.out.println(list);
//进行排序
Collections.sort(list);
System.out.println(list);//[a0, a2, a3, a4, a99]
//元素交换,打印交换后的集合
Collections.swap(list,0,4);
System.out.println(list);//[a99, a2, a3, a4, a0]
//打印集合中最大的元素的角标
System.out.println(Collections.max(list));
//二分法查找,查找前必须排序,如果没有找到就返回负数
Collections.sort(list);
int a=Collections.binarySearch(list,"a88");
if(a>0){
System.out.printf("有这个数,位置在第%d位",a);
}else {
System.out.println("没有这个数");
}
//填充,也就是把集合中所有的元素替换成新的元素
//Collections.fill(list,"a9");
//System.out.println(list);//[a9, a9, a9, a9, a9]
//同步
Collections.synchronizedList(list);
System.out.println(list);
//shuffle随机
Collections.shuffle(list);
System.out.println(list);
}
}
反转 reverseOrder
反转其实是将比较器进行反转,例如前面的例子中的按照字符串的长度的升序排序的,现在要变成降序了,我们就不用再去写多一个比较器了,可以直接用升序的这个比较器去反转,然后传入反转的这个比较器就可以了。
数组变集合:
数组变集合,需要注意的是:我们通过数组转换成的集合,不能对该集合做增删操作,因为数组的长度是固定的,所以不能对其做改变其结构的操作,增删就是对其的结构进行了改变,我们可以做get,contains等操作。
public class Test2 {
public static void main(String[] args) {
String[] a={"a1","a3","a5","a99"};
System.out.println(a);
List<String> list= Arrays.asList(a);
System.out.println(list);
}
}
集合变数组:
集合变数组就简单啦。直接调用集合的toArray() 方法即可;
但有一点需要注意的是:我们在转换成数组的时候,还可以使用这个方法的重载方法,也就是传入一个指定数组。这里需要注意的是,如果集合的长度大于数组的长度,那么就会丢失数据,如果集合长度小于数组的长度,那么就会使后面的数据全部为空。
8、表格数据存储
1、每一行数据使用一个map
整个表格使用一个list
public class Test2 {
public static void main(String[] args) {
Map<String,Object> row1=new HashMap<>();
row1.put("id",10001);
row1.put("name","高琪");
row1.put("age","18");
Map<String,Object> row2=new HashMap<>();
row2.put("id",10002);
row2.put("name","娜娜");
row2.put("age","18");
Map<String,Object> row3=new HashMap<>();
row3.put("id",10003);
row3.put("name","西西");
row3.put("age","18");
List<Map<String,Object>> table=new ArrayList<>();
table.add(row1);
table.add(row2);
table.add(row3);
for(Map<String,Object> row:table){
Set<String> set=row.keySet();
System.out.println(set);
for (String key:set){
System.out.printf(row.get(key)+"\t");
}
System.out.println();
}
}
}
2、使用ORM思想
ORM思想:对象关系映射
每一行数据使用一个:javabean对象
整个表格使用一个map/list
public class Test2 {
public static void main(String[] args) {
School sh1=new School(1,"清华大学","北京");
School sh2=new School(1,"北京大学","北京");
School sh3=new School(1,"复旦大学","上海");
//使用list
List<School> ls=new ArrayList<>();
ls.add(sh1);
ls.add(sh2);
ls.add(sh3);
System.out.println(ls);
for(School s:ls){
System.out.println(s);
}
//使用map
Map<Integer,School> map=new HashMap<>();
map.put(1,sh1);
map.put(2,sh2);
map.put(3,sh3);
//有一个Map对象,这时候使用keySet()方法获取所有的key值
Set<Integer> keyset=map.keySet();
for (Integer key:keyset){
System.out.println(key+"----"+map.get(key));
}
}
}
class School{
private int id;
String name;
String address;
public School() {
}
public School(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
@Override
public String toString() {
return "School{" +
"id=" + id +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
9、遍历方法总结
//遍历list:普通for循环
for(int i=0;i<list.size();i++){
String temp=(String)list.get(i);
System.out.println(temp);
}
//遍历list:增强for循环,使用泛型
for(String temp:list){
System.out.println(temp);
}
//遍历list:使用Iterator迭代器1
for(Iterator itera=list.iterator();itera.hasNext();){
String temp=(String)itera.next();
System.out.println(temp);
}
//遍历list:使用Iterator迭代器2
Iterator itera=list.iterator();
for(itera.hasNext()){
Object obj=itera.next();
iter.remove();//如果遍历时,需要删除集合中的元素,建议使用这个方式
System.out.println(obj);
}
//遍历Map方法:根据key获取对应的value
Map<Integer,String> map=new HashMap<>();
Set<Integer> keyset=map.Keyset();
for(Integer id:keyset){
System.out.println(map.get(id).name);
}
//遍历map方法二:使用entryset
Set<Entry<Integer,Map>> ss=maps.entrySet();
for(Iterator iterator=ss.iterator();iterator.hasNext()){
Entry e=(Entry)iterator.next();
System.out.println(e.getKey()+"-----"+e.getValue());
}