——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——
泛型:JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制。
泛型好处:
1.将运行时的异常转换到了编译时期,以便于程序员处理
2.避免了强转的麻烦
用<>来操作引用数据类型
什么时候定义泛型呢?
1.在集合中较为常见
2.只要见到<>就要定义泛型
当使用集合时,将集合中储存的数据类型作为参数传递给<>即可
泛型定义在类上时,若类中的方法使用该泛型,那么在类建立对象后该方法能操作的引用数据类型就确定了。
泛型定义在方法上时,放在void的前面,并且可以操作多种引用数据类型
静态方法的泛型只能定义在方法上,因为静态优先于对象而存在。
class Demo<T>
{
public void show(T t)
{
System.out.println("show"+t);
}
public <W> void function(W w)
{
System.out.println("function"+w);
}
public static <M> void method(M m)
{
System.out.println("method"+m);
}
}
interface Inter<T>//泛型定义在接口上
{
void show(T t);
}
class Demo2 implements Inter<String>//Demo2后可以不用写泛型,因为泛型已经确定
{
public void show(String s)
{
System.out.println("show2....."+s);
}
}
class Demo3<T> implements Inter<T>//泛型的引用数据类型不确定时,Demo3后一定要加泛型
{
public void show(T t)
{
System.out.println("show3...."+t);
}
}
class GenericDemo
{
public static void main(String[] args)
{
Demo2 d = new Demo2();
d.show("jujuju");
Demo3<Integer> d3 = new Demo3<Integer>();
d3.show(4);
Demo<String> d = new Demo<String>();
d.show("haha");
//d.show(2);//编译会失败,因为show方法所传入的数据类型已经确定,为String
d.function("heiehie");
d.function(3);
//Demo<String>.method("heheheh");//调用时不能带泛型,会编译失败
Demo.method(4);
}
}
Map集合:
Map
Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。他和TreeSet集合一样,有两种方法给集合中的元素排序,一般会按照键排序。
Map集合和Set集合很像。其实Set集合底层就是使用了Map集合。
Map集合没有迭代器,取出Map集合中的键和值的两种方法
第一种方法:
1.通过调用keySet方法会将所有的键存储到Set集合中,在通过Set集合的迭代器取出键
2.通过Map集合的get方法可以取出值
第二种方法:
1.通过调用entrySet方法会将键和值的关系存储到Set集合中,再通过Set集合的迭代器取出他们的映射关系
2.他们的映射关系是一个接口,通过调用该接口的getKey()和getValue()方法可以取出键和值
定义一个学生的类有姓名,年龄
每个学生都有地址
认为姓名和年龄相同的学生为同一个人,要求保证学生的唯一性
思路:
1.描述学生
2.用一个集合将学生存储
3.取出元素
import java.util.*;
class Student implements Comparable<Student>
{
private String name ;
private int age;
Student(String name,int age)
{
this.name = name ;
this.age = age;
}
//覆盖hashCode方法,保证对象的唯一性
public int hashCode()
{
return this.name.hashCode()+age*12;
}
//覆盖equals方法,让其按照指定的方式比较
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException();
Student s = (Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
public int compareTo(Student s)
{
int num = this.name.compareTo(s.name);
if(num==0)
return new Integer(this.age).compareTo(new Integer(s.age));
return num;
}
public void setName(String name)
{
this.name = name ;
}
public String getName()
{
return name;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
public String toString()
{
return name+"-----"+age;
}
}
class HashMapTest
{
public static void main(String[] args)
{
HashMap<Student,String> hm = new HashMap<Student,String>();
hm.put(new Student("lishi01",21),"beijing");
hm.put(new Student("lishi02",25),"shanghai");
hm.put(new Student("lishi01",21),"nanjin");
hm.put(new Student("lishi01",21),"beijing");
hm.put(new Student("lishi05",18),"tianjin");
//取出Map集合中的元素:第二种方法,将键和值的关系存储到Set集合中
Set<Map.Entry<Student,String>> entry = hm.entrySet();
//调用Set集合中的迭代器
Iterator<Map.Entry<Student,String>> ite = entry.iterator();
while (ite.hasNext())
{
Map.Entry<Student,String> me = ite.next();
Student stu = me.getKey();
String str = me.getValue();
System.out.println(stu.toString()+"...|||..."+str);
}
//取出Map集合中的元素:第一种方法,将所有的键存储到Set集合中
Set<Student> key = hm.keySet();
//调用Set集合中的迭代器
Iterator<Student> it = key.iterator();
while (it.hasNext())
{
Student s = it.next();
String value = hm.get(s);
System.out.println(s+"......."+value);
}
}
}
Map集合的应用:
给一个字符串”adaddecgg”要求将每个字符出现的次数打印
打印方式为a(2)c(1)d(3)……..
分析:
在将字符串遍历的过程中,将字符作为键,次数作为值存到集合中
然后在将集合中的元素按照规定的方式打印
步骤:
1.将字符串转为字符数组
2.定义一个具有键值的集合,因为需要排序所以选择TreeMap集合
3.遍历数组中的元素,并将字符作为键,次数作为值存入到集合中
存入时需要判断,按照键取出其对应的值,若值为null,则将字符和1存入
若值不为null,则将值取出并自增后在和字符一起存入
4.遍历集合,若要集合中的元素按照规定的方法打印,可以将键和值存入到一个容器后在取出
import java.util.*;
class MapTest
{
public static void main(String[] args)
{
String s = getCount("aabdecb++--saadde");
System.out.println(s);
}
public static String getCount(String str)
{
char[] cha = str.toCharArray();
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
int count = 0 ;
for (int x=0;x<cha.length ;x++ )
{
Integer value = tm.get(cha[x]);
if(!(cha[x]>='a' && cha[x]<='z' || cha[x]>='A' && cha[x]<='Z'))
continue ;//若不在这个范围就直接让本次循环结束,然后进行下一次的循环
if (value!=null)
count = value;//判断value有没有值,若有则用count记录后然后自增,若没有就不会记录,直接自增一次
count++;
//将字符作为键,出现的次数作为值存入TreeMap集合
tm.put(cha[x],count);
count = 0 ;//因为count定义在成员位置上,会累加,所以每次用完后需要清零
/*
if(value==null)
{
tm.put(cha[x],1);
}
else
{
value++;
tm.put(cha[x],value);
}
*/
}
//定义一个容器用来将集合中取出的键和值以指定的形式存入,然后返回
StringBuilder sb = new StringBuilder();
Set<Character> key = tm.keySet();
Iterator<Character> it = key.iterator();
while (it.hasNext())
{
Character key1 = it.next();//用char接收也可以
Integer value = tm.get(key1);//用int接收也可以
//System.out.print(key1+"("+value+")");
sb.append(key1+"("+value+")");
}
return sb.toString();
}
}
集合框架的工具类。
Collections:集合框架的工具类。里面定义的都是静态方法。
Collections和Collection的区别:
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
它有两个常用的子接口,
List:对元素都有定义索引。有序的。可以重复元素。
Set:不可以重复元素。无序。
Collections是集合框架中的一个工具类。该类中的方法都是静态的
提供的方法中有可以对list集合进行排序,二分查找,替换反转,加锁等。
通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
Arrays:用于操作数组的工具类。里面都是静态方法,它提供了很多对数组进行操作的方法(查阅API文档)。
asList:将数组变成list集合。
把数组变成list集合有什么好处?
可以使用集合的思想和方法来操作数组中的元素。
注意:将数组变成集合,不可以使用集合的增删方法。因为数组的长度是固定。
如果增删。那么会反生UnsupportedOperationException
如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
集合变数组。
Collection接口中的toArray方法。
T[] toArray(T[] a)
如 String[] arr = 集合对象.toArray(new String[集合对象.size()]);
为什么要将集合变数组?
为了限定对元素的操作,不需要进行增删了。
高级for循环
格式:
for(数据类型 变量名 : 被遍历的集合(Collection)或者数组)
{
}
对集合进行遍历。
只能获取集合元素。但是不能对集合进行操作。
import java.util.*;
class ForDemo
{
public static void main(String[] args)
{
ArrayList<String> al = new ArrayList<String>();
al.add("abc1");
al.add("abc2");
al.add("abc3");
for(String s : al)
{
System.out.println(s);
}
int[] arr = {3,5,1};
for(int x=0; x<arr.length; x++)
{
System.out.println(arr[x]);
}
for(int i : arr)
{
System.out.println("i:"+i);
}
HashMap<Integer,String> hm = new HashMap<Integer,String>();
hm.put(1,"a");
hm.put(2,"b");
hm.put(3,"c");
Set<Integer> keySet = hm.keySet();
for(Integer i : keySet)
{
System.out.println(i+"::"+hm.get(i));
}
// Set<Map.Entry<Integer,String>> entrySet = hm.entrySet();
// for(Map.Entry<Integer,String> me : entrySet)
for(Map.Entry<Integer,String> me : hm.entrySet())
{
System.out.println(me.getKey()+"------"+me.getValue());
}
}
}
方法的可变参数。
在使用时注意:可变参数一定要定义在参数列表最后面。
可变参数:可以理解为将这些参数封装成了相对应的数组后传入。
其实就是数组参数的简写形式。不用每一次都手动的建立数组对象。只要将要操作的元素作为参数传递即可,隐式将这些参数封装成了数组。
class ParamMethodDemo
{
public static void main(String[] args)
{
show("haha",2,3,4,5,6);
}
public static void show(String str,int... arr)
{
System.out.println(str+"....."+arr.length);
}
}
import static 静态导入,导入类中所有的静态成员。
当类名重名时,需要指定具体的包名。
当方法重名时,指定具体所属的对象或者类。
需要理解和掌握的一些其他对象
System类 获取和更改系统的属性信息,有可以和流相结合的一些方法。
Properties类 是Map集合,键值都是String,可以与流相结合
Runtime类 getRuntime方法 exec方法等
Date类 DateFormat类 Calendar类 对时间进行操作
Date d = new Date();
将模式封装到SimpleDateformat对象中。
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy年MM月dd日E hh:mm:ss”);
调用format方法让模式格式化指定Date对象。
String time = sdf.format(d);
Math类 包含用于执行基本数学运算的方法
public static void mehthod()
{
for (int x=0;x<10 ;x++ )
{
Random r = new Random();
int d = r.nextInt(10)+1;
//int d = (int)(Math.random()*10+1);//伪随机数
}
double d = Math.ceil(-12.56);//返回大于指定数的最小整数
double d1 = Math.floor(-12.56);//返回小于指定数的最大整数
long l = Math.round(-12.22);//四舍五入
double d2 = Math.pow(3,2);//3^2
}