java基础学习笔记4
string
String
不可变的字符序列:比如要在一个字符串后面追加一串字符,S1=S1+S2;内存里面是重新开辟了一个内存S3,然后把S1,S2分别复制到S3,并没有改变原来的S1,S2。
内存分析:
String a1="hello";
String a2="hello";
// a1==a2为true
// 因为两个hello是相同的字符串,
// 所以在内存里只需要用一个内存就行了,引用指向他即可
a1=new String("hello");
a2=new String("hello");
// a1==a2比较的是内存位置,所以为false
// a1.equals(a2)是重写的方法,比较的是内容,所以是true
char[] b={'h','i',' ','u','f','o'};
String b1=new String(b); //"hi ufo"
String b2=new String(b,1,3);//"i u"
常用方法:
String a1="helloworld.My name is ufo!I love java !";
System.out.println(a1.charAt(3));//第4个字符是啥
System.out.println(a1.length());//长度
System.out.println(a1.indexOf("java"));//第一次出现java的索引位置
System.out.println(a1.indexOf("Java"));//一次都没出现就返回-1
System.out.println(a1.equals("qiuwdw"));//false
System.out.println(a1.equalsIgnoreCase("HELLOWORLD.My name is ufo!I love java !"));//忽略大小写的比较相等 true
System.out.println(a1.replace("o","lalala"));
//里面要么都是char,要么都是String,不能一个是char一个是string
System.out.println(a1.startsWith("hello"));
System.out.println(a1.toUpperCase());//转大写
System.out.println(a1.substring(5));//从位置5开始到最后
System.out.println(a1.trim());//去除两端所有空格
int i=123123;
System.out.println(String.valueOf(i));//把int转为字符串,不仅int,double,char,short,long等基本类型都可以
String a2="q,o,w,i,d,n,q,w,d,q,o,n,,d,q,o,i,n,w,,d,我,饿,佛,法,哦,为,妇女";
String[] a3=a2.split(",");//分割
System.out.println(a3.length);//28
System.out.println(a3[27]);//"妇女"
StringBuffer
StringBuffer
可变的字符序列
声明StringBuffer时必须new,不能直接给他字符串:
StringBuffer a=“sdcwe”;错误的!
StringBuffer a=new StringBuffer(“sdcwe”);正确的!
常用方法:
StringBuffer b1 = new StringBuffer("hello");
b1.append(" i am ufo");//追加字符串"hello i am ufo"
b1.insert(7,"charu");//第七个位置插入
System.out.println(b1.reverse());//倒叙
基础数据类型包装类
int 的包装类Integer,char 的包装类Character
doule float short long 的包装类是各自首字母大写
首先看Integer:(更多细节可以自己去看API文档)
声明:
Integer a=new Integer("a");//报错
Integer a=new Integer("123123");//123123
Integer a=new Integer('a');//97
Math
Math
Math.E//e的值 Math.random()//0-1随机产生一个值
Math.pow(x,3) Math.sqrt(144) Math.round(4.5)//四舍五入
Math.toRadians(60) //60°化成π/3
Math.toDegrees(Math.PI/4 ) //π/4化成45°
File
File
注意,他存的是文件的路径或者是目录的路径
并不是真正的文件!
separator,表示路径分隔符,根据不同系统使用不同分隔符
用法:
String spe= File.separator;
String dirPATH="D:"+spe+"filetest"; // 打印出来是D:\filetest
//接下来尝试创建一个文件
String filename="filetest.txt";
File a=new File(dirPATH,filename);
if (a.exists()){
System.out.println("这个文件存在啦!!他的绝对路径是:"+a.getAbsolutePath());
System.out.println("他的文件大小是:"+a.length());
System.out.println("他可以被写入吗?"+a.canWrite());
}
else{
a.getParentFile().mkdirs();//在他的上级目录中创建这个目录
//然后再创建这个文件,需要try catch
try {
a.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
再次运行:
练习:展示层级目录:
public static void main(String[] args) {
File f = new File("D:\\BaiduNetdiskDownload\\M音乐\\华晨宇");
System.out.println(f.getName());
tree(f, 1);
}
private static void tree(File f, int level) {
String preStr = "";
for(int i=0; i<level; i++) {
preStr += " ";
}
File[] childs = f.listFiles();
for(int i=0; i<childs.length; i++) {
System.out.println(preStr + childs[i].getName());
if(childs[i].isDirectory()) {
tree(childs[i], level + 1);
}
}
}
结果:
Enum
枚举Enum
为什么用它?要求一个变量只能从规定好的几个值当中去取值。
更多用法参考官方API文档。
public class enumtets {
//枚举类型直接写元素进去,不用加引号
public enum Myfavorite {
milk, eggs, vegetable, musics, games;
}
public static void main(String[] args) {
Myfavorite a = Myfavorite.milk;
System.out.println(a);//打印milk
System.out.println(a instanceof Myfavorite);//true,说明a是Myfavorite类型,不是String类型
switch (a) {
case milk:
System.out.println("I like milk");
break;
case eggs:
System.out.println("I like eggs");
break;
}
}
}
Collection
容器
collection的接口:
Collections
Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集 合中元素进行排序、搜索以及线程安全等各种操作。
排序(Sort) 混排(Shuffling)反转(Reverse) 替换所有的元素(Fill) 拷贝(Copy)
返回Collections中最小元素(min) …等等
HashSet
举例:
定义两个类,Person和Animal,
一个重写了equals和hashcode,一个没重写equals和hashcode
注意:重写equals和hashcode有个快捷方式:
当然,也可以自己重写这两个构造方法!
class Person {
int id;
String name;
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
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 Person(int id, String name) {
this.id = id;
this.name = name;
}
}
class Animal {
int id;
String name;
@Override
public String toString() {
return "Animal{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
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 Animal(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public boolean equals(Object a) {
if (a instanceof Animal) {
Animal b = (Animal) a;
if (name.equals(b.getName()) && id == b.getId()) {
return true;
}
}
return super.equals(a);
}
}
主函数:
public static void main(String[] args) {
Collection m = new HashSet();//此处用Collection,可以方便以后换其他类型,不限于HashSet
//HashSet 有序 不可重复 比较的是equals,
m.add("hello");
// m.remove("hello");
//String的equals重写了,所以可以remove
m.add(new Person(12, "ufo"));
m.remove(new Person(12, "ufo"));
// //Person的equals方法没没重写,相当于比较的内存位置,所以不能remove掉
//
m.add(new Animal(12, "Monkey"));
m.remove(new Animal(12, "Monkey"));
// //Animal的equals方法重写了,所以可以remove掉
System.out.println(m);//[hello, Person{id=12, name='ufo'}]
}
只需记住,重写equals还要记得重写hashCode。
Iterator迭代器
通过Collection对象.iterator获取到这个对象的iterator,
然后通过获取到的这个iterator进行遍历。
public static void main(String[] args) {
Collection m = new HashSet();
m.add(new Person(12, "ufo1"));
m.add(new Person(12, "ufo2"));
m.add(new Person(12, "ufo3"));
m.add(new Person(12, "ufo4"));
Iterator i=m.iterator();
while (i.hasNext()){
//i.hasNext返回的true or false
//i.next返回的是object,需要自己转换类型
Person a=(Person)i.next();
System.out.println(a);
//打印Person{id=12, name='ufo3'}
//Person{id=12, name='ufo4'}
//Person{id=12, name='ufo1'}
//Person{id=12, name='ufo2'}
}
}
List
List
LinkedList
举例:add set remove
public static void main(String[] args) {
List m = new LinkedList();
//可重复
m.add(new Music("m1", 100, "aa"));
m.add(new Music("m1", 100, "aa"));
m.add(new Music("m1", 100, "aa"));
m.add(new Music("m1", 100, "aa"));
m.add("abc");//加在最后面
m.add(1,"zxc");//加在指定位置后面
m.set(0,"qwe");//修改指定位置的元素
m.remove(1);//去除指定位置元素
m.remove( new Music("m1", 100, "aa"));//去除第一个匹配到的指定元素
System.out.println(m);
}
举例:sort shuffle reverse
sort时需要list里面的对象类需要实现Comparable<>接口,重写了compareTo方法!
举例:
public static void main(String[] args) {
List m = new LinkedList();
m.add("qwe");
m.add("123");
m.add("q12we");
m.add("123");
m.add("234s");
Collections.sort(m);
//打印 [123, 123, 234s, q12we, qwe]
}
Comparable接口和compareTo方法
compareTo
返回0表示this == obj
返回正数表示this > obj
返回负数表示this < obj
举例:
重点:类实现Comparable,<>中括号里面啥也不填,表示默认传入Object对象
public class Music implements Comparable<Music> {
String name;
int playtime;
String artist;
@Override
public String toString() {
return "Music{" +
"name='" + name + '\'' +
", playtime=" + playtime +
", artist='" + artist + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Music music = (Music) o;
return playtime == music.playtime &&
Objects.equals(name, music.name) &&
Objects.equals(artist, music.artist);
}
@Override
public int hashCode() {
return Objects.hash(name, playtime, artist);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPlaytime() {
return playtime;
}
public void setPlaytime(int playtime) {
this.playtime = playtime;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public Music(String name, int playtime, String artist) {
this.name = name;
this.playtime = playtime;
this.artist = artist;
}
@Override
@Override
public int compareTo(Music o) {
return name.compareTo(o.getName());
}
}
调用:
public static void main(String[] args) {
List m = new LinkedList();
m.add(new Music("m1", 100, "aa"));
m.add(new Music("m2", 100, "aa"));
m.add(new Music("m3", 100, "aa"));
m.add(new Music("007m", 100, "aa"));
Collections.sort(m);
//打印[Music{name='007m', playtime=100, artist='aa'}, Music{name='m1', playtime=100, artist='aa'}, Music{name='m2', playtime=100, artist='aa'}, Music{name='m3', playtime=100, artist='aa'}]
}
如何选择数据结构
衡量标准:读的效率和改的效率
Array读快改慢
Linked改快读慢
Hash两者之间
Map
键值不能重复,
key–value value必须是个对象,不能是基础数据类型
JDK1.5以后可以自动打包或者解包
HashMap
哈希表实现
TreeMap
二叉树实现,红黑树实现
例子:
统计单词数量:
private static final int ONE = 1;
public static void main(String args[]) {
Map m = new HashMap();
for (int i = 0; i < args.length; i++) {
int freq = (Integer) m.get(args[i]) == null ? 0 : (Integer) m.get(args[i]);
m.put(args[i], freq == 0 ? ONE : freq + 1);
}
System.out.println
(m.size() + " distinct words detected:");
System.out.println(m);
}
}
传入参数:
运行:
泛型
起因
JDK1.4以前类型不明确:
装入集合的类型都被当作Object对待,从而失去自己的实际类型。
从集合中取出时往往需要转型,效率低,容易产生错误。
解决办法
在定义集合的时候同时定义集合中对象的类型
可以在定义Collection的时候指定
也可以在循环时用Iterator指定
好处
增强程序的可读性和稳定性
例如:List就只能放String类型
List<String> c = new ArrayList<String>();
c.add("aaa");//里面只能装String
c.add("bbb");
c.add("ccc");
c.add(new person());//报错,只能装String
例如:Map也可以指定键值对类型
Map<String, Integer> m = new HashMap();