①Eclipse常见问题:
1)程序的编译和运行的环境配置
window -- Preferences -- Java
编译环境:Compiler 默认选中的就是最高版本。
运行环境:Installed JREs 默认会找你安装的那个JDK。建议配置了Java的环境变量。
问题:
低编译,高运行。可以。
高编译,低运行。不可以。
建议,编译和运行的版本一致。
2)如何去掉默认注释
window -- Preferences -- Java -- Code Style -- Code Templates
选择你不想要的内容,通过右边Edit编辑。
注意:请只删除注释部分,不是注释部分的不要删除。
3)行号的显示和隐藏
显示:在代码区域的最左边的空白区域,右键 -- Show Line Numbers即可。
4)字体大小及颜色
a:Java代码区域的字体大小和颜色:
window -- Preferences -- General -- Appearance -- Colors And Fonts -- Java修改 -- Java Edit Text Font
b:控制台
window -- Preferences -- General -- Appearance -- Colors And Fonts -- Debug -- Console font
c:其他文件
window -- Preferences -- General -- Appearance -- Colors And Fonts -- Basic -- Text Font
5)窗体给弄乱了,怎么办
window -- persperctive -- Reset Perspective
6)控制台找不到了,怎么办
window--Show View—Console
7)eclipse生成帮助文档
项目编写完毕后--右键--Export--Java--Javadoc—Finish
8)eclipse中打jar包和使用jar包
jar是什么?
•jar是多个class文件的压缩包。
jar有什么用?
•用别人写好的东西
打jar包
•选中项目--右键--Export--Java--Jar--自己指定一个路径和一个名称--Finish
使用jar包
•复制到项目路径下并添加至构建路径。
9)其它
如何查看项目所在路径
•选中 -- 右键 -- Properties -- Resource -- Location
导入项目要注意的问题
•项目区域中不可能出现同名的项目(新建或者导入)
•自己随意建立的文件夹是不能作为项目导入的
修改项目问题
•不要随意修改项目名称
•如果真要修改,不要忘记了配置文件.project中的
•<name>把这里改为你改后的名称</name>
②常用类:
API(Application Programming Interface) :应用程序编程接口 ----------->别人封装好了让我们用
1)Object
Object类概述
•类层次结构的根类
•所有类都直接或者间接的继承自该类
构造方法
•public Object()
•回想面向对象中为什么说:
•子类的构造方法默认访问的是父类的无参构造方法
Object类的成员方法 --------->看帮助文档有详细的解释。
public int hashCode()
public final Class getClass()
public String toString()
public boolean equals(Object obj)
protected void finalize()
protected Object clone()
2)Scanner类:JDK5以后用于获取用户的键盘输入 ----------->交互。
构造方法
•public Scanner(InputStream source)
注意事项
Scanner input = new Scanner(System.in);
int age=input.nextInt();
String name=input.nextLine();
System.out.println(name+":"+age); 输入12回车输出 :12
原因:nextLine()方法如其名,会读取当前这一整行包括换行符。
解决:都以字符串形式接收,然后把字符串转成int类型。
3)String:Java没有内置的字符串类型,所以,就在Java类库中提供了一个类String 供我们来使用
•字符串是由多个字符组成的一串数据(字符序列)
•字符串可以看成是字符数组
•字符串是常量,它的值在创建之后不能更改
构造方法
•public String()
•public String(byte[] bytes)
•public String(byte[] bytes,int offset,int length)
•public String(char[] value)
•public String(char[] value,int offset,int count)
•public String(String original)
面试题
•String s = new String(“hello”)和String s = “hello”;的区别?
常量值不可更改(常量池唯一性),但是变量的引用却是可改的
所以,前者创建2个对象,后者创建1个对象。
看程序说结果----------->字符串引用修改的时候,会去方法区的常量池中比较,相同的话就不再创建。
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
System.out.println(s3==s1+s2); false
System.out.println(s3=="hello"+"world"); true 常量编译时优化
String类的判断功能
boolean equals(Object obj) -------------->这个方法是Object的,String重写了
boolean equalsIgnoreCase(String str)
boolean contains(String str)
boolean startsWith(String str)
boolean endsWith(String str)
boolean isEmpty()
String类的获取功能
int length()
char charAt(int index)
int indexOf(int ch) ------>有点别扭。文档是这么说的:值为 ch
的字符,这里是字符的编码表示。
int indexOf(String str)
int indexOf(int ch,int fromIndex)
int indexOf(String str,int fromIndex)
String substring(int start)
String substring(int start,int end)
String类的转换功能
byte[] getBytes()
char[] toCharArray()
static String valueOf(char[] chs)
static String valueOf(int i)
String toLowerCase()
String toUpperCase()
String concat(String str)
String类的替换功能
•String replace(char old,char new)
•String replace(String old,String new)
去除字符串两空格
•String trim()
按字典顺序比较两个字符串
•int compareTo(String str)
•int compareToIgnoreCase(String str)
4)StringBuffer类:•我们如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。而StringBuffer就可以解决这个问题
构造方法
•public StringBuffer()
•public StringBuffer(int capacity)
•public StringBuffer(String str)
添加功能
•public StringBuffer append(String str)
•public StringBuffer insert(int offset,String str)
删除功能
•public StringBuffer deleteCharAt(int index)
•public StringBuffer delete(int start,int end)
替换功能
•public StringBuffer replace(int start,int end,String str)
反转功能 public StringBuffer reverse()
5)排序和查找
冒泡排序:相邻的元素比较,每一次比较,都会得到一个最值
public static void bobbleSort(int[] arr){
for(int i=0;i<arr.length-1;i++){ -------->需要比较多少遍
for(int j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
插入排序:从下标1开始,逐个与前边元素进行比较,不符合规则互换,将数组分为有序和无序两部分。
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = i; (j > 0) && (arr[j] < arr[j - 1]); j--) {
int temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
}
}
}
选择排序:前n-1个元素,依次与剩余的元素进行比较,不符合规则互换。
public static void selectSort(int[] arr){
for(int i=0;i<arr.length-1;i++){ ------>依次拿出元素与剩余的比较
for(int j=i+1;j<arr.length;j++){
if(arr[i]>arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
二分查找
public static int getIndex(int[] arr,int value){
//定义最大索引,最小索引
int max = arr.length -1;
int min = 0;
//计算出中间索引
int mid = (max +min)/2;
//拿中间索引的值和要查找的值进行比较
while(arr[mid] != value){
if(arr[mid]>value){
max = mid - 1;
}else if(arr[mid]<value){
min = mid + 1;
}
//加入判断
if(min > max){
return -1;
}
mid = (max +min)/2;
}
return mid;
}
6)Arrays
Arrays类概述
•针对数组进行操作的工具类。
•提供了排序,查找等功能。
成员方法
•public static String toString(int[] a) ------>源码可以看看
•public static void sort(int[] a) 底层是快排。
•public static int binarySearch(int[] a,int key) ↑同上
7)基本类型包装类的概述
Integer
源码
Integer num6=new Integer(10);
Integer num7=new Integer(10);
System.out.println("比较结果:"+(num6==num7));
System.out.println("比较结果:"+(num6.equals(num7)));
System.out.println("-------------------");
Integer num8=128;
Integer num9=128;
System.out.println("比较结果:"+(num8==num9));
System.out.println("比较结果:"+(num8.equals(num9)));
System.out.println("-------------------");
Integer num10=new Integer(128);
Integer num11=new Integer(128);
System.out.println("比较结果:"+(num10==num11));
System.out.println("比较结果:"+(num10.equals(num11)));
运行结果:
反编译代码:Integer有自动装箱机制,比较两个integer值是否相等,最好使用equals方法。
Integer integer = new Integer(10);
Integer integer1 = new Integer(10);
System.out.println((new StringBuilder()).append("比较结果:").append(integer == integer1).toString());
System.out.println((new StringBuilder()).append("比较结果:").append(integer.equals(integer1)).toString());
System.out.println("-------------------");
Integer integer2 = Integer.valueOf(128);
Integer integer3 = Integer.valueOf(128);
System.out.println((new StringBuilder()).append("比较结果:").append(integer2 == integer3).toString());
System.out.println((new StringBuilder()).append("比较结果:").append(integer2.equals(integer3)).toString());
System.out.println("-------------------");
Integer integer4 = new Integer(128);
Integer integer5 = new Integer(128);
System.out.println((new StringBuilder()).append("比较结果:").append(integer4 == integer5).toString());
System.out.println((new StringBuilder()).append("比较结果:").append(integer4.equals(integer5)).toString());
Calendar设置月份后过去当月天数的错位
Calendar rightNow = Calendar.getInstance();
for (int i = 1; i < 13; i++) {
rightNow.set(Calendar.MONTH, i);
System.out.println(rightNow.get(Calendar.MONTH)+"月");
System.out.println("这个月的天数:"+rightNow.getActualMaximum(Calendar.DAY_OF_MONTH));
System.out.println("---------------");
}
输出结果:设置月份,获取月份都是正确的,但是如果想获取当月有多少,需要将设置的月份减一,万恶的洋人。
1月
这个月的天数:28
---------------
2月
这个月的天数:31
---------------
3月
这个月的天数:30
---------------
4月
这个月的天数:31
---------------
5月
这个月的天数:30
集合中只可以存储引用数据类型。
解释:原因是因为集合是泛型类,会有边界擦除
Set set=new HashSet<>();
set.add(1); 为什么可以加了呢?
boolean result = set.contains(1);
System.out.println(result); //true
System.out.println(set.size()); //1
编译后,反编译查看代码:
HashSet hashset = new HashSet();
hashset.add(Integer.valueOf(1));
boolean flag = hashset.contains(Integer.valueOf(1));
System.out.println(flag);
System.out.println(hashset.size());
ListIteriator实现逆序遍历。。。
List list=new ArrayList();
list.add("h");
list.add("e");
ListIterator li2 = list.listIterator();
while(li2.hasNext()){
System.out.println(li2.next()); ------>先正序,才可以逆序。。。
}
System.out.println("-------------------------");
ListIterator li = li2;
while(li.hasPrevious()){
System.out.println(li.previous());
}
迭代器查询时修改问题:java.util.ConcurrentModificationException
*也可以通过for循环来解决迭代器的问题。
List list=new ArrayList();
list.add("h");
list.add("e");
list.add("l");
list.add("l");
list.add("o");
Iterator it = list.iterator();
while(it.hasNext()){
String string=(String) it.next();
if(string.equals("e")){
list.add(" world"); 查的过程中改,迭代器报错
}
}
解决方法:
ListIterator li = list.listIterator();
while(li.hasNext()){
String string=(String) li.next();
if(string.equals("e")){
li.add(" world");
}
}
System.out.println(list);
数组的内存图解
集合的继承体系:
常用的数据结构
数组和链表
栈和队列
案例:去除ArrayList中重复的元素。
for (int i = 0; i < array.size(); i++) {
Object obj = array.get(i);
int lastIndex;
while(i!=(lastIndex = array.lastIndexOf(obj))){
array.remove(lastIndex);
}
}
————————————————————————————————————————————————————↑自己写的
for (int x = 0; x < array.size() - 1; x++) {
for (int y = x + 1; y < array.size(); y++) {
if (array.get(x).equals(array.get(y))) { ----》虽然使用了多态,还是常量字符串的比较
array.remove(y);
y--; ----------->遍历过程中删除了元素自然得更新下标
}
}
}
集合的一些方法之间是存在依赖的:contains是通过equals来进行比较的。引用类型集合使用contains方法需要重写equals方法
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
自定义成员变量比较
return true;
}
通过LinkedList来实现栈的效果。
public class MyStack {
private LinkedList link;
public MyStack() {
link = new LinkedList();
}
public void add(Object obj) {
link.addFirst(obj);
}
public Object get() {
// return link.getFirst();
return link.removeFirst();
}
public boolean isEmpty() {
return link.isEmpty();
}
}
泛型的声明:
* ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
* ? extends E:向下限定,E及其子类
* ? super E:向上限定,E极其父类
public class ObjectTool<T> { ------->类的声明语法
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
——————————————————————————————————————————————————————
public <T> void show(T t) { ------------>方法的声明语法
System.out.println(t);
}
——————————————————————————————————————————————————————
public class InterImpl<T> implements Inter<T> { -------->接口子类的声明,为什么要记这些。。
}
Object中hashcode()源码。
native方法的解释:Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。
在定义一个native method时,并不提供实现体(有些像定义一个java interface),因为其实现体是由非java语言在外面实现的。
参考的别人的文章:https://blog.youkuaiyun.com/itmrchen/article/details/53065883
public native int hashCode();
哈希表:有点像某压缩方法,只要是同样的东西,就可以压缩为32个字符。通过字符将实际内容与内存之间取得某种联系。
参考别人的文章:https://blog.youkuaiyun.com/xiaoxik/article/details/74926090
TreeSet部分源码(个人向)
interface Collection {...}
interface Set extends Collection {...}
interface NavigableMap {
}
class TreeMap implements NavigableMap {
public V put(K key, V value) {
Entry<K,V> t = root; ② 每次进来先把旧的给t
if (t == null) { ③ 第一次添加,有效验证之后加上就ok
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp; ④ 否则就是非空,进行排序
Entry<K,V> parent; ⑤定义一个空的盒子
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) { ↑ ⑥ 看看是否有自定义的比较规则
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
do { ⑦ 如果没有自定义的比较规则,通过默认的规则找到位置
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0) ⑧ 新建元素,进行添加。
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
}
class TreeSet implements Set {
private transient NavigableMap<E,Object> m;
public TreeSet() {
this(new TreeMap<E,Object>());
}
public boolean add(E e) {
return m.put(e, PRESENT)==null; ① 调用了TreeMap实现的put方法
}
}
真正的比较是依赖于元素的compareTo()方法,而这个方法是定义在 Comparable里面的。
所以,你要想重写该方法,就必须是先 Comparable接口。这个接口表示的就是自然排序。
实现了Comparable接口的类需要实现compareTo()方法,传入一个外部参数进行比对,实现了Comparator接口的方法需要实现compare()方法,对外部传入的两个类进行比较,从而让外部方法在比较时调用。
两者的区别是实现Comparator接口代码更加灵活,可以定义某个类的多个比较器,从而在排序时根据实际场景自由调用,而Comparable接口实现后便不能改动
参考:https://www.cnblogs.com/andywithu/p/7239613.html
案例:HashSet产生10个1-20之间不同的随机数
例子很简单,但是自己思路错了,记录于此,while循环内部应该是条件成立时才会进行的操作。所以在写条件的时候顺手就写了hs.size()<11,后来一想是错的判断为0时就有0个元素,9→9。11就多了。。。
Random random = new Random();
HashSet<Object> hs = new HashSet<>();
while(hs.size()<10){
int num=random.nextInt(20)+1;
hs.add(num);
}
System.out.println(hs);
HashSet如何保持唯一性,添加方法是通过hashcode()和equals()方法区分是否一样的,将两个方法与成员变量值进行绑定就ok
TreeSet添加原理图解