This page needs a recent browser (with SharedArrayBuffer support). Please update Chrome, Edge, Firefox or Safari to the latest version. · Esta página precisa de um navegador recente (com suporte a SharedArrayBuffer). Por favor, atualize Chrome, Edge, Firefox ou Safari para a versão mais recente.
Every Java program lives inside a class 类. It starts at a method 方法 named main. System.out.println(...) prints a line; System.out.print(...) prints with no new line.
Java is compiled 编译: the compiler 编译器 checks the whole program, then it runs.
Every statement 语句 ends with a semicolon ;.
Português
Todo programa Java vive dentro de uma classe. Começa em um método chamado main. System.out.println(...) imprime uma linha; System.out.print(...) imprime sem nova linha.
public class Main {
public static void main(String[] args) {
System.out.println("Hello, world!");
System.out.println("I am learning Java.");
}
}
Java é compilado 编译: o compiler 编译器 verifica todo o programa, depois ele roda.
Toda statement 语句 termina com ponto e vírgula ; ;.
Programas Java vivem em uma class e começam em main
1.2
Variáveis & tipos primitivos
English
A variable 变量 must declare 声明 its type. Common primitive types 基本类型: int (whole number), double (decimal), boolean (true/false), char (one letter).
Português
Uma variável 变量 deve declarar 声明 seu tipo. Tipos primitivos comuns 基本类型: int (número inteiro), double (decimal), boolean (true/false), char (uma letra).
public class Main {
public static void main(String[] args) {
int age = 17;
double price = 9.99;
boolean passed = true;
System.out.println(age + " " + price + " " + passed);
}
}
1.3
Comentários e estilo
English
A comment 注释 is // (one line) or /* ... */ (a block). Indent the code inside braces { }. Class names start Capitalised; variables and methods use camelCase 驼峰命名 (lowercase first).
Common mistakes
Every statement ends with a semicolon ;.
main must be exactly public static void main(String[] args).
println adds a new line; print does not.
Português
Um comentário 注释 é // (uma linha) ou /* ... */ (um bloco). Indente o código dentro das chaves { }. Os nomes das classes começam com Maiúscula; as variáveis e métodos usam camelCase 驼峰命名 (primeira letra em minúscula).
public class Main {
public static void main(String[] args) {
// greet the user
String firstName = "Mei";
System.out.println("Hi, " + firstName);
}
}
Erros comuns
Toda statement termina com ponto e vírgula ; ;.
main deve ser exatamente public static void main(String[] args).
Java arithmetic 算术 uses + - * / and % (remainder). With two ints, / is integer division 整数除法 — it drops the decimal. +=, -=, and ++ are shortcuts.
Português
A aritmética Java 算术 usa + - * / e % (resto). Com dois ints, / é divisão inteira 整数除法 — ela descarta o decimal. +=, -= e ++ são atalhos.
public class Main {
public static void main(String[] args) {
int a = 7, b = 2;
System.out.println(a / b); // 3 (integer division)
System.out.println(a % b); // 1
double x = 7.0 / 2; // 3.5 (one side is double)
System.out.println(x);
}
}
int/int trunca; use um double para obter um quociente real
2.2
Usando objetos: String, Math, wrappers
English
Some values are objects 对象 with methods. String has .length(), .substring(), .toUpperCase(). Math has Math.max, Math.sqrt, Math.pow. Wrapper classes 包装类 (Integer, Double) wrap a primitive — e.g. Integer.parseInt("42").
Math.random() returns a random 随机double from 0.0 up to (but not including) 1.0. Scale it and cast to get whole numbers — this is the AP idiom:
Integer.MAX_VALUE (2147483647) and Integer.MIN_VALUE are the limits of int; going past them wraps around (an overflow).
An object variable that points at no object holds null; calling a method on it throws a NullPointerException.
Português
Alguns valores são objetos 对象 com métodos. String tem .length(), .substring(), .toUpperCase(). Math tem Math.max, Math.sqrt, Math.pow. Classes wrapper 包装类 (Integer, Double) encapsulam um primitivo — por exemplo, Integer.parseInt("42").
public class Main {
public static void main(String[] args) {
String s = "Hello";
System.out.println(s.length()); // 5
System.out.println(s.toUpperCase()); // HELLO
System.out.println(Math.max(3, 9)); // 9
System.out.println(Integer.parseInt("42") + 1); // 43
}
}
Math.random() retorna um número aleatório 随机 double de 0.0 até (mas não incluindo) 1.0. Escalonar e converter para obter números inteiros — esta é a expressão idiomática do AP:
public class Main {
public static void main(String[] args) {
// a random whole number from 1 to 6 (a dice roll)
int roll = (int) (Math.random() * 6) + 1;
System.out.println(roll >= 1 && roll <= 6); // true
}
}
Integer.MAX_VALUE (2147483647) e Integer.MIN_VALUE são os limites de int; passar deles faz o valor voltar ao início (estouro).
Uma variável de objeto que aponta para nenhum objeto contém null; chamar um método nela lança um NullPointerException.
2.3
Casting & type conversion · Conversão de tipo & casting
English
A cast 强制转换 changes a value's type. (int) drops the decimal; (double) avoids integer division when you need an exact result.
Common mistakes
Integer division: 5 / 2 is 2, not 2.5. Cast first: (double) 5 / 2.
Compare Strings (and other objects) with .equals(), not ==.
== on two objects tests whether they are the SAME object, not whether they look equal.
Português
Uma conversão de tipo 强制转换 muda o tipo de um valor. (int) descarta o decimal; (double) evita a divisão inteira quando você precisa de um resultado exato.
public class Main {
public static void main(String[] args) {
double pi = 3.99;
System.out.println((int) pi); // 3
int total = 7, n = 2;
System.out.println((double) total / n); // 3.5
}
}
Erros comuns
Divisão inteira: 5 / 2 é 2, não 2.5. Converta primeiro: (double) 5 / 2.
Compare Strings (e outros objetos) com .equals(), não ==.
== em dois objetos testa se eles são o MESMO objeto, não se parecem iguais.
if runs a block when a condition 条件 is true; else if and else add more cases. The condition goes in ( ), the block in { }.
Português
if executa um bloco quando uma condição 条件 é verdadeira; else if e else adicionam mais casos. A condição vai em ( ), o bloco em { }.
public class Main {
public static void main(String[] args) {
int score = 72;
if (score >= 80) {
System.out.println("A");
} else if (score >= 60) {
System.out.println("B");
} else {
System.out.println("fail");
}
}
}
Compare with ==, !=, <, >, <=, >= — a comparison 比较 gives a boolean. Combine with && (and), || (or), ! (not) — the logical operators 逻辑运算符. For Strings, use .equals(...), not==.
Português
Compare com ==, !=, <, >, <=, >= — uma comparação 比较 resulta em um valor booleano boolean. Combine com && (e), || (ou), ! (não) — os operadores lógicos 逻辑运算符. Para Strings, use .equals(...), não==.
public class Main {
public static void main(String[] args) {
int age = 16;
boolean member = true;
System.out.println(age >= 18 && member); // false
String a = "hi";
System.out.println(a.equals("hi")); // true
}
}
3.3
switch · interruptor
English
switch chooses among many fixed values. Each case ends with break; default is the fallback.
Common mistakes
A condition must be a boolean; if (x = 5) does not compile (use ==).
Each switch case needs a break;, or control falls through to the next case.
&& and || are the logical operators; & and | are bitwise.
Português
switch escolhe entre muitos valores fixos. Cada case termina com break; default é o caso padrão (fallback).
public class Main {
public static void main(String[] args) {
int day = 3;
switch (day) {
case 1: System.out.println("Mon"); break;
case 3: System.out.println("Wed"); break;
default: System.out.println("other");
}
}
}
Erros comuns
Uma condição deve ser um valor booleano boolean; if (x = 5) não compila (use ==).
Cada caso switch precisa de um break break;, caso contrário o controle cairá no próximo caso.
&& e || são operadores lógicos; & e | são bitwise.
A while loop repeats while a condition is true. Change something inside, or it loops forever.
Português
Um loop while repete enquanto uma condição for verdadeira. Altere algo dentro, ou ele rodará para sempre.
public class Main {
public static void main(String[] args) {
int n = 1;
while (n <= 3) {
System.out.println(n);
n++;
}
}
}
while verifica a condição antes de cada passagem do corpo
4.2
for loops · loops for
English
A for loop packs the start, the condition, and the step into one line. Best when you know the count.
Português
Um loop for agrupa o início, a condição e o passo em uma única linha. Ideal quando você conhece a contagem.
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
System.out.print(i + " ");
}
System.out.println(); // 0 1 2 3 4
}
}
4.3
Acumulação
English
The accumulator 累加器 pattern: start a variable before the loop, then update it each turn.
Português
O padrão acumulador 累加器: inicie uma variável antes do loop, depois atualize-a a cada iteração.
public class Main {
public static void main(String[] args) {
int total = 0;
for (int i = 1; i <= 5; i++) {
total += i;
}
System.out.println(total); // 15
}
}
4.4
Laços aninhados
English
A loop inside a loop is a nested loop 嵌套循环. The inner loop runs fully on each turn of the outer one.
Common mistakes
for (int i = 0; i < n; i++) runs n times (0 to n - 1); using <= runs one extra.
Do not put a semicolon right after for (...) or while (...) — it makes an empty loop.
Declare the counter in the for header so its scope ends with the loop.
Português
Um loop dentro de outro é um loop aninhado 嵌套循环. O loop interno roda completamente em cada iteração do externo.
public class Main {
public static void main(String[] args) {
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
System.out.print("*");
}
System.out.println();
}
}
}
Erros comuns
for (int i = 0; i < n; i++) executa n vezes (de 0 até n - 1); usar <= executa uma vez a mais.
Não coloque ponto e vírgula logo após for (...) ou while (...) — isso cria um loop vazio.
Declare o contador no cabeçalho do for para que seu escopo termine com o loop.
A String 字符串 is text. Useful methods: .length(), .charAt(i), .substring(a, b), .indexOf(x), .toUpperCase(), .equals(...). Strings are immutable 不可变 — each method returns a new String.
The methods you will use every day:
Method
Meaning
Example → result
.length()
how many characters
"Hi".length() → 2
.charAt(i)
one character
"Hi".charAt(0) → H
.substring(a, b)
part, stops before b
"Python".substring(0, 3) → Pyt
.substring(a)
from a to the end
"Python".substring(3) → hon
.indexOf(x)
first position, -1 if absent
"banana".indexOf("na") → 2
.equals(s)
same text?
"hi".equals("hi") → true
.compareTo(s)
order: negative / 0 / positive
"apple".compareTo("banana") → negative
compareTo puts Strings in dictionary order — the AP exam uses it for sorting questions:
Português
Uma String String 字符串 é texto. Métodos úteis: .length(), .charAt(i), .substring(a, b), .indexOf(x), .toUpperCase(), .equals(...). Strings são imutáveis 不可变 — cada método retorna uma nova String.
public class Main {
public static void main(String[] args) {
String s = "Python";
System.out.println(s.length()); // 6
System.out.println(s.charAt(0)); // P
System.out.println(s.substring(0, 3)); // Pyt
System.out.println(s.toUpperCase()); // PYTHON
}
}
Os métodos que você usará todos os dias:
Método
Significado
Exemplo → resultado
.length()
quantos caracteres
"Hi".length() → 2
.charAt(i)
um caractere
"Hi".charAt(0) → H
.substring(a, b)
parte, para antes de b
"Python".substring(0, 3) → Pyt
.substring(a)
de a até o final
"Python".substring(3) → hon
.indexOf(x)
primeira posição, -1 se ausente
"banana".indexOf("na") → 2
.equals(s)
mesmo texto?
"hi".equals("hi") → true
.compareTo(s)
ordem: negativo / 0 / positivo
"apple".compareTo("banana") → negativo
compareTo coloca Strings em ordem dicionária — o exame AP usa isso para perguntas de ordenação:
public class Main {
public static void main(String[] args) {
String a = "apple", b = "banana";
System.out.println(a.compareTo(b) < 0); // true (apple comes first)
System.out.println(a.compareTo("apple")); // 0 (equal)
}
}
Métodos principais de String: length, charAt, substring, equals
5.2
Construindo e percorrendo strings
English
Join strings with + (concatenation 拼接). Visit each character with a loop and .charAt(i).
When you build a long String in a loop, StringBuilder is much faster: append the pieces, then call .toString() once.
Common mistakes
Strings are immutable: s.toUpperCase() returns a new String, so store the result.
Read a character with s.charAt(i); the length is s.length() (a method, with ()).
Building a String with += in a big loop is slow; use a StringBuilder.
Português
Junte strings com + (concatenação 拼接). Acesse cada caractere com um loop e .charAt(i).
public class Main {
public static void main(String[] args) {
String word = "banana";
int count = 0;
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) == 'a') count++;
}
System.out.println(count); // 3
}
}
Ao construir uma String longa em um loop, StringBuilder é muito mais rápido: append as peças, depois chame .toString() uma vez.
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 5; i++) {
sb.append(i).append(" ");
}
System.out.println(sb.toString().trim()); // 1 2 3 4 5
}
}
Erros comuns
Strings são imutáveis: s.toUpperCase() retorna uma nova String, então armazene o resultado.
Leia um caractere com s.charAt(i); o comprimento é s.length() (um método, com ()).
Construir uma String com += em um loop grande é lento; use um StringBuilder.
An array 数组 holds a fixed number of values of one type. Index from 0, and get the size with .length.
Português
Um array 数组 guarda um número fixo de valores de um único tipo. Indexe de 0 e obtenha o tamanho com .length.
public class Main {
public static void main(String[] args) {
int[] scores = {88, 71, 95};
System.out.println(scores[0]); // 88
System.out.println(scores.length); // 3
scores[1] = 100;
System.out.println(scores[1]); // 100
}
}
Um primitivo guarda seu valor; uma variável de array guarda uma referência ao objeto array
6.2
Algoritmos de arrays
English
Walk the array with a loop to find a max, a total, a count, or to search 查找. A for-each loop (for (int x : a)) reads each value in turn.
Português
Percorra o array com um loop para encontrar um máximo, um total, uma contagem ou para pesquisar 查找. Um loop for-each (for (int x : a)) lê cada valor por vez.
public class Main {
public static void main(String[] args) {
int[] a = {3, 9, 2, 7};
int max = a[0], total = 0;
for (int x : a) {
if (x > max) max = x;
total += x;
}
System.out.println(max + " " + total); // 9 21
}
}
6.3
Arrays 2-D
English
A 2-D array 二维数组 is a grid 网格 of rows and columns: grid[row][col].
Common mistakes
An array's size is a.length (no brackets, no ()), and it is fixed when created.
Valid indexes are 0 to a.length - 1; a[a.length] throws ArrayIndexOutOfBoundsException.
A new int[5] is filled with zeros, not left empty.
Português
Um array 2-D 二维数组 é uma grade 网格 de linhas e colunas: grid[row][col].
public class Main {
public static void main(String[] args) {
int[][] grid = {{1, 2, 3}, {4, 5, 6}};
System.out.println(grid[1][2]); // 6
for (int[] row : grid) {
for (int v : row) System.out.print(v + " ");
}
System.out.println(); // 1 2 3 4 5 6
}
}
Erros comuns
O tamanho de um array é a.length (sem colchetes, sem ()), e é fixo na criação.
Índices válidos são de 0 a a.length - 1; a[a.length] lança ArrayIndexOutOfBoundsException.
Um novo int[5] é preenchido com zeros, não deixado vazio.
An ArrayList is a resizable 可变大小 list — it grows and shrinks as you add or remove items. It stores objects, so use a wrapper 包装类 type like Integer (not int). The <Integer> part is a generic 泛型 type. Key methods: .add(x), .get(i), .set(i, x), .size(), .remove(i).
Português
Um ArrayList ArrayList é uma lista de tamanho variável 可变大小 — ela cresce e encolhe conforme você adiciona ou remove itens. Ela armazena objetos, então use um tipo wrapper 包装类 como Integer (não int). A parte <Integer> é um tipo genérico 泛型. Métodos principais: .add(x), .get(i), .set(i, x), .size(), .remove(i).
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(10);
nums.add(20);
nums.add(30);
System.out.println(nums.size()); // 3
System.out.println(nums.get(1)); // 20
nums.set(0, 99);
System.out.println(nums); // [99, 20, 30]
}
}
ArrayList: add, get, size em uma lista redimensionável
7.2
Algoritmos de ArrayList e o bug do remove
English
.remove(i) shifts 移动 every later element one place left. If you remove while counting iup, you skip the next element. Fix: loop backwards, or don't increment i after a remove.
Common mistakes
ArrayList uses .size(), .get(i) and .add(...) — not the [] you use on arrays.
Removing items while looping forward by index skips the next item (the remove bug). Loop backwards, or use an iterator.
Store objects, not primitives: use ArrayList<Integer>, and Java auto-boxes int values.
Português
.remove(i) desloca 移动 cada elemento subsequente uma posição para a esquerda. Se você remover enquanto conta ipara cima, pula o próximo elemento. Correção: faça o loop para trás, ou não incremente i após um remove.
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> nums = new ArrayList<Integer>();
for (int n : new int[]{4, 7, 4, 9, 4}) nums.add(n);
// Remove every 4 — loop backwards so removals don't skip items.
for (int i = nums.size() - 1; i >= 0; i--) {
if (nums.get(i) == 4) nums.remove(i);
}
System.out.println(nums); // [7, 9]
}
}
Erros comuns
ArrayList usa .size(), .get(i) e .add(...) — não o [] que você usa em arrays.
Remover itens enquanto itera para frente por índice pula o próximo item (o bug do remove). Itere para trás, ou use um iterator.
Armazene objetos, não primitivos: use ArrayList<Integer>, e Java auto-boxes int valores.
A class 类 is a blueprint for objects. Its fields 字段 store data, its constructor 构造方法 sets up a new object, and its methods 方法 are the actions. this.name means "this object's name". Create an object with new.
A static member belongs to the class itself, not to any one object. Call a static method on the class name — like Math.max — and a static field is shared by every object:
Português
Uma classe 类 é um modelo para objetos. Seus campos 字段 armazenam dados, seu construtor 构造方法 configura um novo objeto, e seus métodos 方法 são as ações. this.name significa "o name deste objeto". Crie um objeto com new.
public class Main {
public static void main(String[] args) {
Dog d = new Dog("Rex", 3);
System.out.println(d.describe()); // Rex is 3 years old
d.haveBirthday();
System.out.println(d.describe()); // Rex is 4 years old
}
}
class Dog {
private String name;
private int age;
public Dog(String name, int age) { // constructor
this.name = name;
this.age = age;
}
public String describe() {
return name + " is " + age + " years old";
}
public void haveBirthday() {
age++;
}
}
Um membro static pertence à classe em si, não a nenhum objeto específico. Chame um método estático pelo nome da classe — como Math.max — e um campo estático é compartilhado por todos os objetos:
public class Main {
public static void main(String[] args) {
System.out.println(Counter.made()); // 0
new Counter();
new Counter();
System.out.println(Counter.made()); // 2
}
}
class Counter {
private static int count = 0; // shared by ALL Counter objects
public Counter() { count++; }
public static int made() { // called on the class: Counter.made()
return count;
}
}
Encapsulation 封装 means hiding data behind methods. Mark fields private so outside code can't touch them directly; expose an accessor 访问方法 (getter) to read, and a method to change them safely. The method can guard the data — here a deposit must be positive.
Common mistakes
A constructor has the class name and no return type (not even void).
Use this.field to tell a field apart from a parameter with the same name.
Make fields private and reach them through getter/setter methods (encapsulation).
Português
Encapsulamento 封装 significa esconder dados atrás de métodos. Marque os campos private para que código externo não possa tocá-los diretamente; exponha um acessor 访问方法 (getter) para ler, e um método para alterá-los com segurança. O método pode proteger os dados — aqui um depósito deve ser positivo.
public class Main {
public static void main(String[] args) {
Account a = new Account(100);
a.deposit(50);
a.deposit(-999); // rejected by the guard
System.out.println(a.getBalance()); // 150
}
}
class Account {
private int balance; // hidden from outside
public Account(int start) {
balance = start;
}
public void deposit(int amount) {
if (amount > 0) balance += amount; // guard keeps balance valid
}
public int getBalance() { // accessor (getter)
return balance;
}
}
Erros comuns
Um construtor tem o nome da classe e nenhum tipo de retorno (nem sequer void).
Use this.field para distinguir um campo de um parâmetro com o mesmo nome.
Torne os campos private e acesse-os através de métodos getter/setter (encapsulamento).
Inheritance 继承 lets a subclass 子类 reuse a superclass 父类. Write class Cat extends Animal and Cat gets Animal's fields and methods for free. Call the parent constructor with super(...).
Português
Herança 继承 permite que uma subclasse 子类 reutilize uma superclasse 父类. Escreva class Cat extends Animal e Cat obtém os campos e métodos de Animal gratuitamente. Chame o construtor pai com super(...).
public class Main {
public static void main(String[] args) {
Cat c = new Cat("Milo");
c.eat(); // Milo is eating (inherited from Animal)
c.speak(); // Meow (Cat's own method)
}
}
class Animal {
protected String name;
public Animal(String name) { this.name = name; }
public void eat() { System.out.println(name + " is eating"); }
}
class Cat extends Animal {
public Cat(String name) { super(name); } // call Animal's constructor
public void speak() { System.out.println("Meow"); }
}
Gato e Cão estendem Animal: eles herdam seus membros e adicionam os próprios
9.2
Polimorfismo e toString
English
A subclass can override 重写 a method to replace the parent's version. Polymorphism 多态 means a Shape variable can hold any subtype, and Java picks the right toString at run time. System.out.println(obj) automatically calls obj.toString().
Common mistakes
An overriding method must match the signature exactly; add @Override so the compiler catches slips.
super(...) must be the first line of a subclass constructor.
A subclass object IS-A superclass object, but not the other way round.
Português
Uma subclasse pode sobrescrever 重写 um método para substituir a versão do pai. Polimorfismo 多态 significa que uma variável Shape pode conter qualquer subtipo, e Java escolhe o toString correto em tempo de execução. System.out.println(obj) chama obj.toString() automaticamente.
public class Main {
public static void main(String[] args) {
Shape[] shapes = { new Circle(2), new Square(3) };
for (Shape s : shapes) {
System.out.println(s); // each calls its own toString
}
}
}
class Shape {
public String toString() { return "a shape"; }
}
class Circle extends Shape {
private int r;
public Circle(int r) { this.r = r; }
public String toString() { return "Circle r=" + r; } // override
}
class Square extends Shape {
private int side;
public Square(int side) { this.side = side; }
public String toString() { return "Square side=" + side; } // override
}
Erros comuns
Um método sobrescrito deve corresponder exatamente à assinatura; adicione @Override para que o compilador capture erros.
super(...) deve ser a primeira linha de um construtor de subclasse.
Um objeto de subclasse É-UM objeto de superclasse, mas não o contrário.
Recursion 递归 is a method that calls itself. Every recursion needs a base case 基准情形 (when to stop) and a recursive call 递归调用 that moves toward it. Without a base case it never stops and crashes with a stack overflow.
Trace it: factorial(5) waits for factorial(4), which waits for factorial(3)… down to factorial(1) returning 1. Then the answers multiply back up: 1 → 2 → 6 → 24 → 120.
Recursion also works on Strings — peel off one character each call:
Merge sort 归并排序 is the recursive sort on the AP exam: split the array in half, sort each half recursively, then merge 合并 the two sorted halves. It runs in O(n log n) — far faster than the O(n²) sorts on big arrays.
Common mistakes
Recursion needs a base case, or it throws StackOverflowError.
Each recursive call must move CLOSER to the base case.
Trace a small example by hand to check the recursion returns the right value.
In merge sort, the merge step does the real work; the recursion only splits the array.
Português
Recursão 递归 é um método que se chama a si mesmo. Toda recursão precisa de um caso base 基准情形 (quando parar) e uma chamada recursiva 递归调用 que se aproxime dele. Sem um caso base, nunca para e falha com stack overflow.
A pilha de chamadas para factorial(3): cada chamada espera, depois retorna em ordem inversa
public class Main {
public static void main(String[] args) {
System.out.println(factorial(5)); // 120
}
public static int factorial(int n) {
if (n <= 1) return 1; // base case
return n * factorial(n - 1); // recursive call: n * (n-1)!
}
}
Rastreie: factorial(5) espera por factorial(4), que espera por factorial(3)… até factorial(1) retornar 1. Depois as respostas multiplicam de volta para cima: 1 → 2 → 6 → 24 → 120.
Recursão também funciona em Strings — remova um caractere por chamada:
public class Main {
public static void main(String[] args) {
System.out.println(reverse("PYTHON")); // NOHTYP
}
static String reverse(String s) {
if (s.length() <= 1) return s; // base case
return reverse(s.substring(1)) + s.charAt(0);
}
}
Merge sort 归并排序 é a ordenação recursiva no exame AP: divida o array pela metade, ordene cada metade recursivamente, depois combine 合并 as duas metades ordenadas. Ele roda em O(n log n) — muito mais rápido que as ordenações O(n²) em arrays grandes.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] a = {5, 2, 9, 1, 7, 3};
mergeSort(a, 0, a.length - 1);
System.out.println(Arrays.toString(a)); // [1, 2, 3, 5, 7, 9]
}
static void mergeSort(int[] a, int lo, int hi) {
if (lo >= hi) return; // base case: one element
int mid = (lo + hi) / 2;
mergeSort(a, lo, mid); // sort the left half
mergeSort(a, mid + 1, hi); // sort the right half
merge(a, lo, mid, hi); // merge the two halves
}
static void merge(int[] a, int lo, int mid, int hi) {
int[] tmp = new int[hi - lo + 1];
int i = lo, j = mid + 1, k = 0;
while (i <= mid && j <= hi) {
if (a[i] <= a[j]) tmp[k++] = a[i++];
else tmp[k++] = a[j++];
}
while (i <= mid) tmp[k++] = a[i++];
while (j <= hi) tmp[k++] = a[j++];
for (k = 0; k < tmp.length; k++) a[lo + k] = tmp[k];
}
}
Erros comuns
A recursão precisa de um caso base, ou lança StackOverflowError.
Cada chamada recursiva deve se mover PARA PERTO do caso base.
Rastreie um pequeno exemplo manualmente para verificar se a recursão retorna o valor correto.
No merge sort, o passo de combinação faz o trabalho real; a recursão apenas divide o array.
Linear search 线性查找 checks every element — works on any array. Binary search 二分查找 is much faster but needs a sorted 已排序 array: it looks at the middle, then throws away half each step. Both return the index, or -1 if not found.
Português
Busca linear 线性查找 verifica cada elemento — funciona em qualquer array. Busca binária 二分查找 é muito mais rápida, mas precisa de um array ordenado 已排序: olha para o meio, depois descarta metade a cada passo. Ambas retornam o índice, ou -1 se não encontrado.
public class Main {
public static void main(String[] args) {
int[] a = {2, 5, 8, 12, 16, 23}; // sorted, so binary search works
System.out.println(linear(a, 12)); // 3
System.out.println(binary(a, 12)); // 3
System.out.println(binary(a, 9)); // -1 (not found)
}
static int linear(int[] a, int target) {
for (int i = 0; i < a.length; i++)
if (a[i] == target) return i;
return -1;
}
static int binary(int[] a, int target) {
int lo = 0, hi = a.length - 1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (a[mid] == target) return mid;
else if (a[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
}
A busca binária reduz a faixa pela metade a cada passo, então um array ordenado é buscado em O(log n)
11.2
Ordenação por seleção e inserção
English
Selection sort 选择排序 repeatedly finds the smallest remaining value and swaps it to the front. Insertion sort 插入排序 takes each value and slides it back into its place among the already-sorted values.
How the speeds compare:
Algorithm
Time
linear search
O(n)
binary search
O(log n), sorted arrays only
selection / insertion sort
O(n²)
merge sort (topic 10)
O(n log n)
Common mistakes
Binary search only works on a sorted array.
Linear search is O(n); binary search is O(log n) but needs the sort first.
Selection and insertion sort are O(n²) — clear to learn, slow on big data.
Português
Ordenação por seleção 选择排序 encontra repetidamente o menor valor restante e o troca para a frente. Ordenação por inserção 插入排序 pega cada valor e o desliza para trás no lugar entre os valores já ordenados.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] a = {5, 2, 9, 1, 7};
for (int i = 0; i < a.length - 1; i++) {
int min = i;
for (int j = i + 1; j < a.length; j++)
if (a[j] < a[min]) min = j;
int t = a[min]; a[min] = a[i]; a[i] = t; // swap into place
}
System.out.println(Arrays.toString(a)); // [1, 2, 5, 7, 9]
}
}
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] a = {5, 2, 9, 1, 7};
for (int i = 1; i < a.length; i++) {
int key = a[i], j = i - 1;
while (j >= 0 && a[j] > key) { // shift bigger values right
a[j + 1] = a[j];
j--;
}
a[j + 1] = key; // drop key into the gap
}
System.out.println(Arrays.toString(a)); // [1, 2, 5, 7, 9]
}
}
Como as velocidades se comparam:
Algoritmo
Tempo
busca linear
O(n)
busca binária
O(log n), apenas arrays ordenados
seleção / inserção
O(n²)
merge sort (tópico 10)
O(n log n)
Erros comuns
A busca binária só funciona em um array ordenado.
A busca linear é O(n); a busca binária é O(log n), mas precisa da ordenação primeiro.
Seleção e inserção são O(n²) — claro para aprender, lento em grandes volumes de dados.
A Scanner reads text one line at a time. For a real file you write new Scanner(new File("scores.txt")); here we wrap a String so the example runs anywhere. Use .split(" ") to split 拆分 a line into parts and Integer.parseInt(...) to parse 解析 a number from text.
Português
Um Scanner lê texto linha por linha. Para um arquivo real, escreva new Scanner(new File("scores.txt")); aqui envolvi um String para que o exemplo rode em qualquer lugar. Use .split(" ") para dividir 拆分 uma linha em partes e Integer.parseInt(...) para parsear 解析 um número do texto.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// Real file: Scanner in = new Scanner(new File("scores.txt"));
String data = "Alice 80\nBob 95\nCara 72";
Scanner in = new Scanner(data);
int total = 0, count = 0;
while (in.hasNextLine()) {
String line = in.nextLine();
String[] parts = line.split(" "); // break the line on the space
total += Integer.parseInt(parts[1]);
count++;
}
System.out.println("average = " + (total / count)); // average = 82
}
}
Scanner lê linhas enquanto hasNextLine for true
12.2
Tipos de questões do FRQ do AP
English
The AP CS A exam has four free-response 自由作答 questions, each a fixed shape:
Q1 — Methods & control: write methods to a given spec; loops, if, String/Math.
Q2 — Class design: write a full class (fields, constructor, methods) from a description.
Q3 — Array / ArrayList: process a 1-D array or ArrayList (search, count, build a new list).
Q4 — 2-D array: traverse a grid by row and column.
The skill is always the same: read the spec, write the method exactly as described, return the right type.
Common mistakes
nextInt() leaves the newline behind, so a following nextLine() reads an empty line — read it away first.
Check hasNext() before reading, to avoid running off the end of the file.
In the FRQ, read the method header carefully: match the return type and parameters exactly.
Português
O exame AP CS A tem quatro questões de resposta aberta 自由作答, cada uma com formato fixo:
Q1 — Métodos e controle: escreva métodos segundo uma especificação dada; loops, if, String/Math.
Q2 — Design de classe: escreva uma classe completa (campos, construtor, métodos) a partir de uma descrição.
Q3 — Array / ArrayList: processe um array 1-D ou ArrayList (busca, contagem,=cria uma nova lista).
Q4 — Array 2-D: percorra uma grade por linha e coluna.
A habilidade é sempre a mesma: leia a especificação, escreva o método exatamente como descrito, retorne o tipo correto.
public class Main {
public static void main(String[] args) {
// Q1 style: implement a method to a spec, then it is tested.
System.out.println(countEven(new int[]{4, 7, 10, 3, 6})); // 3
}
/** Returns how many values in arr are even. */
public static int countEven(int[] arr) {
int count = 0;
for (int x : arr)
if (x % 2 == 0) count++;
return count;
}
}
Erros comuns
nextInt() deixa a quebra de linha para trás, então um nextLine() subsequente lê uma linha vazia — leia-a primeiro para removê-la.
Verifique hasNext() antes de ler, para evitar sair do fim do arquivo.
Na FRQ, leia o cabeçalho do método com atenção: corresponda o tipo de retorno e os parâmetros exatamente.
Pick one and the site follows you — notes, papers, videos and practice all open on it. · Escolha uma e o site te seguirá — notas, provas, vídeos e prática abrirão nela.
Type to search notes, lessons, code, vocabulary and past-paper questions across every subject. · Digite para pesquisar notas, aulas, código, vocabulário e questões de provas anteriores em todas as disciplinas.