Лекция 13. Разное¶
Работа с СУБД¶
Рассмотрим работу программы на примере СУБД MySQL
Разработаем два класса:
- MysqlConnect - обслуживание соединения
- DBTest - демонстрационная программа
Схема работы с СУБД:

В системе должны быть установлены драйвера коннектора jdbc-mysql, которые можно скачать по адресу:
http://dev.mysql.com/downloads/connector/j/
Описание класса MysqlConnect:
Пакеты в заголовке:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
class MysqlConnect {
// данные для работы с СУБД
// название драйвера СУБД
private static final String DATABASE_DRIVER =
"com.mysql.jdbc.Driver";
// адрес MySQL с указанием имени базы
private static final String DATABASE_URL =
"jdbc:mysql://localhost:3306/test_java?useSSL=false";
// имя пользователя MySQL
private static final String USERNAME = "root";
// пароль для доступа к базе
private static final String PASSWORD = "123456";
// макс. количество соединений
private static final String MAX_POOL = "250";
..
..
// объект "соединение"
private Connection connection;
// объект "свойства соединения"
private Properties properties;
// метод для формирования записи свойств
private Properties getProperties() {
if (properties == null) {
properties = new Properties();
properties.setProperty("user", USERNAME);
properties.setProperty("password", PASSWORD);
properties.setProperty("MaxPooledStatements", MAX_POOL);
}
return properties;
}
..
Установка соединения:
// connect database
public Connection connect() {
if (connection == null) {
try {
Class.forName(DATABASE_DRIVER);
connection =
DriverManager.getConnection(DATABASE_URL, getProperties());
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
return connection;
}
Разрыв соединения с СУБД:
// disconnect database
public void disconnect() {
if (connection != null) {
try {
connection.close();
connection = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
} // конец описания класса
В главном классе программы создаем соединение и скачиваем записи из таблицы months:
public class DBTest
{
public static void main(String[] args) {
MysqlConnect mysqlConnect = new MysqlConnect();
String sql = "SELECT * FROM `months`";
try {
PreparedStatement statement =
mysqlConnect.connect().prepareStatement(sql);
ResultSet rs = statement.executeQuery();
..
while (rs.next()) {
String num = rs.getString("num");
String name = rs.getString("name");
System.out.println("num : " + num);
System.out.println("name : " + name);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
mysqlConnect.disconnect();
}
}
}
Для запуска программы нужно подключить архив с пакетами драйвера:
java -cp mysql-connector-java-5.1.39-bin.jar:. DBTest
Элементы ФП¶
Функциональная парадигма - это подход к программированию, в центре которого
находится понятие функции (в математическом смысле), а сама программа -
процесс вычисления некоторой функции.
Принципы ФП:
- Объекты неизменяемы (можно создать новый объект, но нельзя изменить старый).
- Функции не имеют побочных эффектов (нет указателей, ссылок на глобальные переменные).
- Функции - параметры.
- Широко применяются безымянные лямбда-функции.
- Используется выведение типов компилятором.
Поддержка ФП была введена в Java 8. Пример с кнопкой:
// обработчик нажатия на кнопку (стиль ООП)
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("button clicked");
}
});
// функциональный стиль
button.addActionListener(event -> System.out.println("button clicked"));
Различные стили записи лямбда-функций:
// функция без аргументов
Runnable noArguments = () -> System.out.println("Hello World");
// функция с одним аргументом
ActionListener oneArgument =
event -> System.out.println("button clicked");
// функция с блоком кода
Runnable multiStatement = () -> {
System.out.print("Hello");
System.out.println(" World");
};
// функция с двумя аргументами
BinaryOperator<Long> add = (x, y) -> x + y;
// явное указание типов аргументов
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
Пример с обработкой коллекции:
import java.util.*;
public class Example1
{
public static void main(String[] args) {
List<String> colors =
Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
// опасный цикл
for(int i=0;i<colors.size();i++)
System.out.println(colors.get(i));
// перебор коллекции
for(String color: colors)
System.out.println(color);
}
}
Вариант перебора:
// перебор с лямбда-функцией
colors.forEach((String color) -> System.out.println(color));
// перебор с лямбда-функцией (сокращенная версия)
colors.forEach(System.out::println);
Вариант с трансформацией списка:
import java.util.*;
public class Example2
{
public static void main(String[] args) {
List<String> colors =
Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
List<String> uppercaseColors = new ArrayList<String>();
colors.forEach(color -> uppercaseColors.add(color.toUpperCase()));
System.out.println(uppercaseColors);
}
}
$ java Example2
[RED, ORANGE, BLUE, WHITE, BLACK, YELLOW]
Другой вариант:
import java.util.*;
public class Example3
{
public static void main(String[] args) {
List<String> colors =
Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
List<String> uppercaseColors = new ArrayList<String>();
colors.stream()
.map(color -> color.toUpperCase())
.forEach(color -> System.out.print(color + " "));
System.out.println();
}
}
Варианты функций, возвращаемые stream():
- .filter() - отбирает элементы, для которых лямбда-функция возвращает true
- .map() - применяет лямбда-функцию к каждому элементу коллекции
- .reduce() - пытается обработать два параметра и отобрать один, затем передать по коллекции дальше
- .collect() - накопление результата при движении по коллекции
Подсчет строк, начинающихся на B:
import java.util.*;
public class Example5
{
public static void main(String[] args) {
List<String> colors =
Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
List<String> uppercaseColors = new ArrayList<String>();
long count=
colors.stream()
.filter(color -> color.startsWith("B"))
.count();
System.out.println(count);
}
}
import java.util.*;
public class Example6
{
public static void main(String[] args) {
List<String> colors =
Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
List<String> uppercaseColors = new ArrayList<String>();
colors.stream()
.map(color -> color.length())
.forEach(color -> System.out.println(color));
System.out.println();
}
}
Программа выводит длины слов
Регулярные выражения¶
Одним из важнейших механизмов поиска и обработки данных
являются регулярные выражения
Для работы подключат пакеты:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Пример использования:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class RegexDemo
{
public static void main(String[] args)
{
Pattern p=Pattern.compile(".*(\\d)+ab.*");
Matcher m=p.matcher("qq5abbb");
System.out.println(m.matches());
System.out.println(m.group(1));
}
}
Взаимодействие с С++¶
Java и CPP¶
Для взаимодействия Java-программ с функциями, написанными на С++, используется
интерфейс JNI
Алгоритм построения совместной программы:
- Пишем код Java-класса
- Компилируем Java-программу
- Создаем заголовочный файл для С++
- Пишем C++файл
- Компилируем C++ файл и получаем динамическую библиотеку
- Запускаем Java-программу
Java-класс:
public class Hello {
// функция С++
public native void hello();
public static void main(String[] args) {
Hello h=new Hello();
h.hello();
}
static {
System.loadLibrary("hello");
}
}
Компиляция Java-программы:
javac Hello.java
Создание заголовочного файла:
javah -jni Hello
Создаем файл hello.c с определением функции hello():
JNIEXPORT void JNICALL Java_Hello_hello(JNIEnv *e, jobject o)
{
printf("Hello from C!");
}
Имя вызываемой функции берем из h-файла. Компилируем С-файл и получаем библиотеку:
g++ -dynamiclib
-o libhello.jnilib
-I/opt/local/lib/gcc47/gcc/x86_64-apple-darwin13/4.7.4/include
hello.c
Здесь в параметре -I указан путь к заголовочному файлу jni.h
Запускаем Java-программу:
java Hello