Образование: ИЕИГН СФУ, Институт математики, 2010г.
Работаю в IT 10 лет, из них в СИС - 8,5 лет.
Старший разработчик программного обеспечения.
Технологии:
Увлечения:
Алан Тьюринг
Машина Тьюринга
Алонзо Чёрч
Лямбда-исчисление
// f(x, y) = x + y * 2
int f(int x, int y) {
return x + y * 2;
}
List<Product> filterByType(
List<Product> products, ProductType type) {
List<Product> result = new ArrayList<>();
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
if (product.getType() == type) {
result.add(product);
}
}
return result;
}
List<Product> filterByType(
List<Product> products, ProductType type) {
List<Product> result = new ArrayList<>();
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
if (product.getType() == type) {
result.add(product);
}
}
return result;
}
List<Product> filterByPrice(
List<Product> products, int threshold) {
List<Product> result = new ArrayList<>();
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
if (product.getPrice() > threshold) {
result.add(product);
}
}
return result;
}
List<Product> filterByProducer(
List<Product> products, String producer) {
List<Product> result = new ArrayList<>();
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
if (product.getProducer().equals(producer)) {
result.add(product);
}
}
return result;
}
List<Product> filterByType(
List<Product> products, ProductType type
) {
List<Product> result = new ArrayList<>();
for (Product product : products) {
if (product.getType() == type) {
result.add(product);
}
}
return result;
}
Предика́т — это функция, которая для каждого набора переданных в нее аргументов возвращает одно из следующих двух значений:
Примеры:
P(x) - x это простое число.
F(d, l) - d является отцом l.
Q(p) - p является продуктом типа "сладкое".
Q(p, t) - p является продуктом типа t.
public interface Predicate {
boolean match(Product value);
}
public class ProductTypePredicate implements Predicate {
private ProductType type;
ProductTypePredicate(ProductType type) {
this.type = type;
}
@Override
boolean match(Product product) {
return product.getType() == this.type;
}
}
// Метод фильтрации товаров
List<Product> filter(List<Product> products, Predicate predicate) {
List<Product> result = new ArrayList<>();
for (Product product : products) {
// Меняем частную бизнес-логику на вызов предиката
if (predicate.match(product)) {
result.add(product);
}
}
return result;
}
Фу́нкция вы́сшего поря́дка — это функция, принимающая в качестве аргументов другие функции и/или возвращающая другую функцию в качестве результата.
Примеры:
List<Product> filterProductsByType(
List<Product> products, ProductType type
) {
Predicate predicate = new ProductTypePredicate(type);
return filter(products, predicate);
}
public class ProductTypePredicate implements Predicate {
private ProductType type;
ProductTypePredicate(ProductType type) {
this.type = type;
}
@Override
boolean match(Product product) {
return product.getType() == this.type;
}
}
List<Product> filterProductsByType(
List<Product> products, ProductType type
) {
return filter(products, item -> item.getType() == type);
}
List<Product> filterProductsByType(
List<Product> products, ProductType type
) {
Predicate predicate = new ProductTypePredicate(type);
return filter(products, predicate);
}
Лямбда-выражение — специальный синтаксис для определения анонимных функций.
// Однострочная лямбда-функция
Predicate predicate =
product -> product.getType() == type;
Параметры
Разделитель
Тело
// Обычная функция
boolean match(Product product) {
return product.getType() == this.type;
}
Тип возвращаемого значения
Predicate predicate = (Product item, double maxPrice) -> {
if (item.getPrice() > maxPrice) {
return item.getType() == type;
}
return false;
};
Параметры
Разделитель
Тело
List<Product> filterByType(
List<Product> products, ProductType type) {
List<Product> result = new ArrayList<>();
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
if (product.getType() == type) {
result.add(product);
}
}
return result;
}
List<Product> filterByPrice(
List<Product> products, int threshold) {
List<Product> result = new ArrayList<>();
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
if (product.getPrice() > threshold) {
result.add(product);
}
}
return result;
}
List<Product> filterByProducer(
List<Product> products, String producer) {
List<Product> result = new ArrayList<>();
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
if (product.getProducer().equals(producer)) {
result.add(product);
}
}
return result;
}
List<Product> filterByType(List<Product> products, ProductType type) {
return filter(products, product -> product.getType() == type);
}
List<Product> filterByPrice(List<Product> products, int threshold) {
return filter(products, product -> product.getPrice() > threshold);
}
List<Product> filterByProducer(List<Product> products, String producer) {
return filter(products, product -> product.getProducer().equals(producer));
}
List<Product> filter(
List<Product> products, Predicate predicate) {
List<Product> result = new ArrayList<>();
for (Product product : products) {
if (predicate.match(product)) {
result.add(product);
}
}
return result;
}
Добавляют новую операцию обработки потока, возвращают новый поток
Примеры:
Завершают работу потока, выполняют все операции, формируют и возвращают результат работы потока
Примеры:
Оператор map
List<Producer> getUniqueProducers(List<Product> products) {
return products.stream()
.map(Product::getProducer)
.distinct()
.collect(Collectors.toList());
}
Оператор sorted
List<Producer> getUniqueSortedProducers(List<Product> products) {
return products
.stream()
.map(Product::getProducer)
.distinct()
.sorted(Comparator.comparing(Producer::getName))
.collect(Collectors.toList());
}
List<Product> filterByType(
List<Product> products, ProductType type) {
return products.stream()
.filter(product -> item.getType() == type)
.collect(Collectors.toList());
}
Оператор filter
List<Product> filterByType(
List<Product> products, ProductType type) {
return products.stream()
.filter(product -> item.getType() == type)
.collect(Collectors.toList());
}
Оператор collect
String getProductsAsString(
List<Product> products) {
return products.stream()
.collect(Collectors.joining());
}
BigDecimal getTotalTax(List<Product> products) {
return products
.stream().map(Product::getPrice)
.map(price -> price.divide(BigDecimal.valueOf(120),
RoundingMode.HALF_EVEN)
.multiply(BigDecimal.valueOf(20)))
.reduce(BigDecimal.ZERO,
(total, current) -> total.add(current));
}
Оператор reduce
Декларативность
- мы описываем, что мы хотим получить
Ленивость
- нет вычислений, пока нам не понадобится результат
Лаконичность
- пишем меньше кода, допускаем меньше низкоуровневых ошибок
Optional<T> findFirst();
Optional?
Product findProductByIdUnsafe(
List<Product> products, long id) {
for (Product product : products) {
if (product.getId() == id) {
return product;
}
}
return null;
}
String extractProductProducerName(Product product) {
return product.getProducer()
.getName();
}
String getProductProducerNameByIdUnsafe(
List<Product> products, long id) {
Product product = findProductByIdUnsafe(products, id);
return extractProductProducerName(product);
}
NullPointerException в рантайме, если товар с таким id не найден
Optional<Product> findProductById(
List<Product> products, long id) {
return products
.stream()
.filter(product -> product.getId() == id)
.findFirst();
}
Optional<Product> вместо Product
String getProductProducerNameById(
List<Product> products, long id) {
Product product = findProductById(products, id);
return extractProductProducerName(product);
}
Ошибка на этапе компиляции, а не NullPointerException в рантайме
String getProductProducerNameById(
List<Product> products, long id) {
Optional<Product> productOptional =
findProductById(products, id);
if (productOptional.isPresent()) {
return extractProductProducerName(
productOptional.get());
} else {
throw new RuntimeException(
String.format(
"Товар с идентификатором '%s' не найден", id));
}
}
String getProductProducerNameById(
List<Product> products, long id) {
Optional<String> nameOptional =
findProductById(products, id)
.map(ProductsService::extractProductProducerName);
if (nameOptional.isPresent()) {
return nameOptional.get();
} else {
throw new RuntimeException(
String.format(
"Товар с идентификатором '%s' не найден", id));
}
}
Ссылка на метод: то же, что и product -> extractProductProducerName(product)
String getProductProducerNameById(
List<Product> products, long id) {
return
findProductById(products, id)
.map(ProductsService::extractProductProducerName);
.orElseThrow(() -> new RuntimeException(
String.format(
"Товар с идентификатором '%s' не найден", id)
)
);
}
Вместо исключения - вернется строка "Неизвестный производитель"
String getProductProducerNameByIdSoft(
List<Product> products, long id) {
return
findProductById(products, id)
.map(ProductsService::extractProductProducerName);
.orElse("Неизвестный производитель");
}
Optional.of не может быть пустым. Если подать в него null, то произойдет исключение в рантайме!
Предметная область:
- грузовые перевозки
Данные:
- есть несколько видов транспорта,
у каждого транспорта своя
стоимость доставки груза и вместимость.
- есть груз, который нужно доставить,
груз имеет список доступных путей
(ж/д, морской, воздушный, ...)
Задание:
- для заданного груза рассчитать оптимальный по затратам способ доставки (наименьшая цена)
Предметная область и данные: см. задачу #5.1
Дополнительные данные и условия:
- есть несколько задач по доставке груза
- есть несколько видов транспорта
- есть диапазон потраченных денег
- мы знаем точно, что была решена одна задача,
но не знаем какая именно
- не факт что все деньги потрачены на задачу :-)
Задание:
Исходный код:
https://github.com/SiberianIntegrationSystems/JavaSIS-3.20/tree/master/unit5
Требования:
Возможные проблемы:
Сущности: