Страницы

Поиск по вопросам

вторник, 22 января 2019 г.

По каким критериям в Java строка попадает в пул строк?

По сути этот вопрос продолжает другой вопрос
Во многих статьях говорится, что при создании строк без new через литерал строка попадает в пул строк. В противном случае необходим метод intern. Как тогда объяснить поведение ниже ?
String s2 = "hello"; String s1 = "hello"; System.out.println(s1 == s2); // true
System.out.println("hel" + "lo" == "hello"); // true
s1 = "hello"; s2 = "hel"; String s3 = "lo";
System.out.println(s1 == s2 + s3); // false System.out.println(s2 + s3 == "hel" + "lo"); //false
Если в последнем случае s2 ссылается туда же куда и литерал "hel", и с s3 такая же история, то почему "hel" + "lo" не равно (по ссылке) s2 + s3 ?


Ответ

Строка может попасть в пул констант в двух случаях:
На этапе компиляции.
Компилятор проходит по всем строкам в исходном коде и добавляет их в пул констант. Если в коде есть какие-то места, в которых нужны вычисления и компилятор может их произвести, то он делает это. В Вашем примере это System.out.println("hel" + "lo" == "hello");. Сконкатенировал "hel" + "lo" и положил в пул.
Вызов String.intern()
Описание метода (ссылка на документацию). Здесь надо обязательно указать границы применения данного способа. Данный методы выглядит очень заманчиво: "мы можем сократить использование памяти, и производительность в програме!! Это громадная оптимизация!!"
Из intern пула НЕ возможно удалить данные intern медленнее чем реализация (через ConcurrentHashMap, например) интернирования. Потому что во внутренней таблице (в которой хранятся интерниованные строки) всего около 60 000 бакетов и большОе количество строк может забить эти бакеты. Покачто эта Map не ресайзится. intern может влиять на работу всей JVM так как таблица используется для хранения информации о классах
Если мне не верите, то Алексею Шипилеву должны поверить (про intern с 32 минуты).

VS 2017. Повторный build проекта

После полного build solution, повторный build один проект пересобирает. Из за чего такое может быть?


Ответ

Потому что в файле проекта была строчка
Always

Практическая разница между Linq To Entites и Linq To Objects

Изучая различия между LINQ To Entites и LINQ To Objects в EntityFramework - столкнулся с интересной вещью :
var phones = db.Phones.Where(p=> p.CompanyId == 1).ToList().Where(p=> p.Id<10);
Здесь используются два метода Where, но их реализация будет различной. В первом случае, db.Phones.Where(p=> p.CompanyId == 1) транслируется в выражение SQL, которое было рассмотрено выше. Далее метод ToList() по результатам запроса создает список в памяти компьютера. После этого мы уже имеем дело со списком в памяти, а не с базой данных. И далее вызов Where(p=> p.Id<10) будет обращаться к списку в памяти и будет представлять Linq to Object.
И мне стало интересно : А не проще ли просто получать нужное значение из БД путем простого обращения через LINQ не используя при этом LINQ To Objects?
Ведь запрос в даном случае будет выглядеть так :
var phones = db.Phones .Where(p => p.CompanyId==1 && p.TelephoneId<10)
Хотелось бы узнать какой подход в данном случае будем эффективней и почему?


Ответ

Смотрите. Базы данных предназначены, кроме всего прочего, и для того, чтобы быстро и эффективно работать с большими объёмами данных. Например, базы данных легко справляются с выборкой из таблиц, больших по размеру, чем оперативная память. А вот получение целой такой таблицы в память с целью последующей фильтрации уже провалится по перерасходу памяти.
Также и фильтрация в базе данных может быть очень быстрой, т. к. если у неё есть индекс на фильтруемое поле, она может совместить фильтрацию с выборкой. (А особо умные базы данных могут, исходя из запросов, такой индекс и выстроить сами.) Если индекса нет, то всё равно польза от фильтрации на стороне базы в том, что выброшенные фильтром данные не нужно перегонять из базы в программу, и не нужно создавать их в основной программе только для того, чтобы тут же выбросить.
Поэтому обычно имеет смысл те части запроса, которые можно выполнить в базе данных (это та часть, при которой вы остаётесь в рамках IQueryable), выполнять на ней.
(Я не уверен, относится ли эта рекомендация к вложенным подзапросам, пускай лучше специалисты по базам данных поправят меня.)
К сожалению, скорость операций на базе данных имеет и обратную сторону: не все операции можно выполнить на базе данных, поэтому промежуточные результаты запроса приходится материализовать (то есть, получать из базы и загружать в память), используя ToList или AsEnumerable, и «дорабатывать напильником» в самой программе.

«Умения» различных баз данных отличаются между собой. Обычно база данных должна уметь фильтровать не только по равенству поля значению, но и уметь сравнивать с константой. Судя по всему, либо вам попался код для менее продвинутой базы данных (да, абстракции протекают), либо автор кода ошибся. Либо это «костыль» под какой-нибудь баг. Если сравнение возможно выполнить на базе данных, его стоит именно там и выполнять.

Как переписать Template deduction guide (С++17) на C++14?

Дан код на С++17:
template struct Ok { T value; }; template<> struct Ok {};
// template deduction guides template Ok(T) -> Ok;
Template deduction guides позволяют имея тип Ok вызывать Ok как функцию (так выглядит, на самом деле вызывается конструктор):
auto c = Ok(5); // T deduced as int // без template deduction guide я так писать не могу, // но должен писать: auto c = Ok(5); // T can not be deduced :(
Вопрос в том, как это переписать на С++14 или ниже? Чтоб я писал просто:
auto c = Ok("hello"s); // T deduced as std::string
Но с произвольным типом.


Ответ

template Ok> makeOk(T&& arg){ return Ok>{std::forward(arg)}; }
auto c = makeOk(5); auto d = makeOk(std::make_unique(6.7));

Ошибка подключение к БД в symfony

Вылил сайт на хостинг и появилась ошибка подключения к базе данных.
You have requested a non-existent parameter "database_name". Did you mean one of these: database
Локально всё работает нормально. В чём может быть ошибка?


Ответ

Скорее всего неправильно задан конфиг в parameters.yml либо в config.yml.
в parameters.yml добавьте:
parameters: database_host: YOUR_HOST database_port: 3306 database_name: DB_NAME database_user: DB_USER database_password: DB_PASS
а в config.yml добавьте подключение к доктрине
doctrine: dbal: default_connection: default connections: default: driver: pdo_mysql host: '%database_host%' port: '%database_port%' dbname: '%database_name%' user: '%database_user%' password: '%database_password%' charset: UTF8

Что такое статический полиформизм?

Наткнулся на такой термин - "статический полиформизм". Не знал про такое сочетание. В гугле особо ничего не нашел.
Кто бы мог дать обьяснение термина + пример?


Ответ

Этим умным словосочетанием обозначают обычную перегрузку методов. Не ту, что имеет место в классах-наследниках, помечаемых словом override, а что-то наподобие:
class Foo { public void some() { // какой-то код }
public void some(int parameter) { // какой-то код } }

Правильное выполнение запроса RxJava+Retrofit

Здравствуйте. Недавно начал разбираться с RxJava. Что-то тяжело пока дается... Есть сервер на котором есть приватные чаты(тет-а-тет) и групповые. Посредством Rest запроса на сервер нужно выудить следующую инфу оттуда: Все существующие чаты и диалоги:
Observable> chats = apiService.getChats(); Observable> dialogs = apiService.getDialogs();
Объекты Chat и Dialog содержат переменные:
int unreadMessagesCount (количество непрочитанных сообщений); int id (по этому id запрашивается список сообщений из чата)
Запросы на список сообщений
Observable> dialogMessages = apiService.getDialogMessages(String id); Observable> chatMessages = apiService.getChatMessages(String id);
Как в этом случае более грамотно составить запросы используя RxJava, чтобы опросить все чаты и диалоги на предмет новых сообщений и затем получить эти сообщения в один список?


Ответ

Например как-то так:
Получаем массив чатов. Преобразуем массив оных в очередь объектов Chat Получаем детали каждого. Результат преобразовываем обратно в массив:.

apiService.getChats() .from(Observable::from) .flatMap(chat -> apiService.getChatMessages(chat.id)) .toList() .subscribe(System::out);
Если без лямбд, то from(Observable::from) можно переписать вот такой ужасной конструкцией:
.flatMap(new Func1, Observable>() { @Override public Observable call(List chats) { return Observable.from(chats); } })