├── 05-generics ├── README.md ├── snippets │ ├── README.md │ └── src │ │ ├── GenericRecord.java │ │ ├── ExoticFruit.java │ │ ├── Container.java │ │ ├── BridgeMethods.java │ │ └── Pair.java └── lecture │ ├── images │ ├── 05.0-java-generics.jpg │ ├── 05.1-collections-subtypes.png │ └── 05.2-o-reilly-generics-and-collections.png │ └── slides.html ├── _config.yml ├── 01-intro-to-java ├── README.md ├── lecture │ ├── images │ │ ├── 01.10-rocket.jpg │ │ ├── 01.11-array.png │ │ ├── 01.12-matrix.jpg │ │ ├── 01.13-funcs.png │ │ ├── 01.8-java-app.png │ │ ├── 01.9-variables.jpg │ │ ├── 01.2-vscode-logo.jpg │ │ ├── 01.1-intellij-logo.jpg │ │ ├── 01.15-effective-java.jpg │ │ ├── 01.3-eclipse-logo.jpeg │ │ ├── 01.4-netbeans-logo.jpg │ │ ├── 01.6-jep-per-release.png │ │ ├── 01.7-hello-world-25.jpeg │ │ ├── 01.14-thinking-in-java.jpg │ │ └── 01.5-java-logo-mascot.png │ └── slides.html ├── snippets │ └── UnnamedClassesExample.java └── lab │ └── 01-unique-substring-finder │ └── README.md ├── 09-threads ├── README.md ├── lab │ └── resources │ │ ├── DECODEME.png │ │ └── producer-consumer.png ├── lecture │ ├── images │ │ ├── 09.1-threads.jpeg │ │ ├── 09.10-deadlock.jpg │ │ ├── 09.8-thread-join.png │ │ ├── 09.9-thread-states.png │ │ ├── 09.3-multi-core-cpus.jpg │ │ ├── 09.4-multithreading.png │ │ ├── 09.2-meaning-of-concurrent.png │ │ ├── 09.5-concurrent-parallel.png │ │ ├── 09.6-platform-virtual-threads.png │ │ ├── 09.11-java-concurrency-in-practice.jpg │ │ └── 09.7-virtual-threads-sharing-carrier.png │ └── slides.html └── snippets │ └── src │ ├── Depositor.java │ ├── JoinExample.java │ ├── DaemonThreads.java │ ├── RaceConditionExample.java │ ├── StaticResourceExample.java │ ├── BankAccount.java │ ├── howmany │ ├── HowManyThreadsHelper.java │ ├── HowManyPlatformThreadsDoingSomething.java │ ├── HowManyPlatformThreads.java │ ├── HowManyVirtualThreadsDoingSomething.java │ └── HowManyVirtualThreads.java │ ├── AtomicIntegerExample.java │ ├── SimpleDeadLock.java │ ├── WaitNotifyExample.java │ ├── NonTrivialDeadLock.java │ └── RaceSimulation.java ├── 04-collections-clean-code ├── README.md ├── snippets │ ├── README.md │ └── src │ │ ├── collections │ │ ├── permissions │ │ │ ├── Permission.java │ │ │ ├── PermissionTracker.java │ │ │ ├── EnumCollectionsDemo.java │ │ │ └── User.java │ │ ├── scheduler │ │ │ └── TaskScheduler.java │ │ └── products │ │ │ └── RecentlyViewedProducts.java │ │ └── comparators │ │ ├── CarByBrandComparator.java │ │ ├── CarByTopSpeedDescComparator.java │ │ ├── Car.java │ │ └── Main.java └── lecture │ ├── images │ ├── 04.5-clean-code.png │ ├── 04.6-collections.png │ ├── 04.14-cheat-sheet.png │ ├── 04.2-wtfs-per-min.png │ ├── 04.3-oracle-google.png │ ├── 04.1-clean-code-zen.png │ ├── 04.10-listperformance.png │ ├── 04.12-setperformance.png │ ├── 04.12.0-linkedhashset.png │ ├── 04.13-mapperformance.png │ ├── 04.7.1-big-o-chart.jpeg │ ├── 04.11-queueperformance.png │ ├── 04.4-static-code-analyzers.png │ ├── 04.7-basic-data-structures.png │ ├── 04.5.1-planetgeek-cheatsheet.png │ ├── 04.7.2-complexity-cheatsheet.png │ └── 04.8-collections-map-hierarchy.jpg │ └── slides.html ├── 06-unit-testing-and-mocking ├── README.md ├── snippets │ ├── README.md │ ├── src │ │ └── bg │ │ │ └── sofia │ │ │ └── uni │ │ │ └── fmi │ │ │ └── mjt │ │ │ ├── exchange │ │ │ ├── Currency.java │ │ │ ├── CurrencyConverter.java │ │ │ ├── UnknownCurrencyException.java │ │ │ ├── GoogleCurrencyConverter.java │ │ │ └── CurrencyExchange.java │ │ │ └── math │ │ │ ├── Calc.java │ │ │ └── NumberUtils.java │ └── test │ │ └── bg │ │ └── sofia │ │ └── uni │ │ └── fmi │ │ └── mjt │ │ ├── math │ │ ├── CalcTest.java │ │ └── NumberUtilsTest.java │ │ └── OrderedTest.java ├── lecture │ ├── images │ │ ├── 06.5-mockito.png │ │ ├── 06.3-more-tests.png │ │ ├── 06.4-junit-logo.jpeg │ │ ├── 06.1-relative-cost.png │ │ ├── 06.2-testing-process.png │ │ ├── 06.0-unit-testing-and-mocking.png │ │ └── 06.6-practical-unit-testing.png │ └── slides.html └── lab │ └── resources │ └── src │ └── bg │ └── sofia │ └── uni │ └── fmi │ └── mjt │ ├── file │ ├── exception │ │ └── EmptyFileException.java │ ├── File.java │ └── step │ │ ├── CountFiles.java │ │ ├── UpperCaseFile.java │ │ ├── CheckEmptyFile.java │ │ ├── PrintFiles.java │ │ └── SplitFile.java │ └── pipeline │ ├── step │ └── Step.java │ └── Cache.java ├── 08-lambdas-and-stream-api ├── README.md ├── snippets │ ├── README.md │ └── src │ │ └── bg │ │ └── sofia │ │ └── uni │ │ └── fmi │ │ └── mjt │ │ ├── employees │ │ ├── Employee.java │ │ └── EmployeesExample.java │ │ ├── ints │ │ └── IntsSum.java │ │ ├── peaks │ │ └── model │ │ │ └── Peak.java │ │ ├── MethRefExample.java │ │ └── gatherers │ │ └── GatherersExample.java └── lecture │ ├── images │ ├── 08.1-lambda.jpg │ ├── 08.0-where-are-we.png │ ├── 08.3-variance-formula.png │ ├── 08.6-z-score-formula.png │ ├── 08.4-average-value-formula.png │ ├── 08.2-stream-operations-pipeline.png │ └── 08.5-standard-deviation-formula.png │ └── slides.html ├── .gitattributes ├── 07-io-streams-and-files ├── README.md ├── snippets │ ├── README.md │ ├── src │ │ └── bg │ │ │ └── sofia │ │ │ └── uni │ │ │ └── fmi │ │ │ └── mjt │ │ │ └── io │ │ │ ├── Student.java │ │ │ ├── SystemStreamsRedirector.java │ │ │ ├── WritingToAndReadingFromFile.java │ │ │ ├── DiskSizeEstimator.java │ │ │ ├── DataStreamExample.java │ │ │ └── ObjectStreamExample.java │ └── test │ │ └── TempFileTest.java ├── lab │ └── resources │ │ ├── car.jpg │ │ └── kitten.png └── lecture │ ├── images │ ├── 07.1-io-streams.png │ ├── 07.2-java-app-io.png │ ├── 07.10-io-apis-wrapup.gif │ ├── 07.5-java-io-classes.png │ ├── 07.11-java-io-nio-nio2.png │ ├── 07.8-wrapping-io-streams.png │ ├── 07.12-maserati-edge-detected.png │ ├── 07.4-java-io-class-hierarchy.png │ ├── 07.8.1-standard-io-streams.png │ ├── 07.3-java-io-root-abstract-classes.png │ ├── 07.6-java-byte-io-classes-hierarchy.png │ └── 07.7-java-char-io-classes-hierarchy.png │ └── slides.html ├── 02-oop-in-java-i ├── snippets │ ├── README.md │ └── src │ │ └── bg │ │ └── sofia │ │ └── uni │ │ └── fmi │ │ └── mjt │ │ ├── overridings │ │ ├── Car.java │ │ ├── Audi.java │ │ ├── Garage.java │ │ └── AudiGarage.java │ │ ├── adorable │ │ ├── Likeable.java │ │ ├── Lovable.java │ │ ├── AbstractCoolPerson.java │ │ ├── Adorable.java │ │ └── CoolPerson.java │ │ ├── lockable │ │ ├── OldLockable.java │ │ ├── Door.java │ │ ├── Vault.java │ │ ├── Safe.java │ │ ├── Lockable.java │ │ └── DefaultInterfaceExamples.java │ │ ├── suuper │ │ └── SuperExample.java │ │ ├── statics │ │ ├── Project.java │ │ └── MethodHidingExample.java │ │ └── instanceoff │ │ └── InstanceOfExample.java ├── README.md └── lecture │ ├── images │ └── 02.1-oop.jpg │ └── slides.html ├── 03-oop-in-java-ii ├── README.md ├── snippets │ ├── README.md │ └── src │ │ ├── records │ │ ├── Point.java │ │ ├── PointDemo.java │ │ ├── Order.java │ │ ├── OrderDemo.java │ │ └── Student.java │ │ ├── exceptions │ │ ├── interfaces │ │ │ ├── Bookable.java │ │ │ └── AirBnB.java │ │ ├── EmailNotFoundException.java │ │ ├── WrongPasswordException.java │ │ ├── signature │ │ │ ├── ExceptionSignatureBase.java │ │ │ └── ExceptionSignature.java │ │ ├── AuthenticationException.java │ │ ├── HelpfulNPE.java │ │ └── SmartNPEExample.java │ │ ├── sealed │ │ ├── Exercise.java │ │ ├── GymWorkout.java │ │ ├── Jogging.java │ │ └── Swimming.java │ │ ├── argumentpassing │ │ ├── PrimitiveArgumentsExample.java │ │ └── ReferencesExample.java │ │ ├── enums │ │ ├── Day.java │ │ ├── StringConstants.java │ │ └── DaysExample.java │ │ ├── heapandstack │ │ └── HeapAndStackExample.java │ │ └── initializers │ │ └── InitializersDemo.java └── lecture │ ├── images │ ├── 03.3.0-enums.png │ ├── 03.6.0-records.png │ ├── 03.6.1-sealed.png │ ├── 03.2-call-stack.png │ ├── 03.3-exceptions.jpeg │ ├── 03.4-exceptions.png │ ├── 03.0-stack-vs-heap.png │ ├── 03.4.0-exceptions.png │ ├── 03.6-sealed-hierarchy-1.png │ ├── 03.6-sealed-hierarchy-2.png │ ├── 03.6-sealed-hierarchy-3.png │ ├── 03.6-sealed-hierarchy-4.png │ ├── 03.1-favorite-new-java-features.png │ └── 03.5-checked-vs-runtime-exceptions.jpeg │ └── slides.html ├── web ├── Designer.png ├── fonts │ ├── remixicon.ttf │ ├── remixicon.woff │ └── remixicon.woff2 └── images │ ├── favicon.png │ ├── java-25.png │ └── mjt-on-youtube.png ├── 10-network ├── README.md ├── snippets │ ├── README.md │ └── src │ │ ├── threadpools │ │ ├── Task.java │ │ ├── CachedThreadPoolExample.java │ │ ├── FixedThreadPoolExample.java │ │ ├── VirtualThreadPoolExample.java │ │ └── ScheduledThreadPoolExample.java │ │ ├── network │ │ ├── InetAddressExample.java │ │ ├── LanIpFinder.java │ │ └── NetworkInterfacesLister.java │ │ ├── threadsafecollections │ │ ├── BlockingQueueExample.java │ │ └── ConcurrentVsSynchronizedMap.java │ │ └── structuredconcurrency │ │ └── StructuredConcurrencyDemo.java └── lecture │ ├── images │ ├── 10.0-networking.jpg │ ├── 10.3-osi-model.png │ ├── 10.4-ipv4-ipv6.png │ ├── 10.1-client-server.png │ ├── 10.2-peer-to-peer.jpg │ └── 09.6-java-concurrency-in-practice.jpg │ └── slides.html ├── .gitignore ├── homeworks └── README.md ├── playground ├── 02-dna-analyzer │ ├── SampleDNAAnalyzerTest.java │ └── README.md ├── README.md ├── 01-stock-exchange │ ├── SampleStockExchangeTest.java │ └── README.md ├── 03-dungeons │ └── SampleDungeonsTest.java └── 04-cryptic-letter │ └── README.md └── docs └── 02-code-analysis-tools └── PMD ├── pmd-rulesets ├── controversial.xml ├── unusedcode.xml ├── braces.xml ├── imports.xml ├── strings.xml ├── codesize.xml ├── strictexception.xml ├── unnecessary.xml ├── junit.xml └── naming.xml └── pmd.xml /05-generics/README.md: -------------------------------------------------------------------------------- 1 | # Generics 2 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /01-intro-to-java/README.md: -------------------------------------------------------------------------------- 1 | # Въведение в Java 2 | -------------------------------------------------------------------------------- /05-generics/snippets/README.md: -------------------------------------------------------------------------------- 1 | # Generics / Code snippets 2 | -------------------------------------------------------------------------------- /09-threads/README.md: -------------------------------------------------------------------------------- 1 | # Многонишково програмиране (Част I) 2 | -------------------------------------------------------------------------------- /04-collections-clean-code/README.md: -------------------------------------------------------------------------------- 1 | # Collections | Clean Code 2 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/README.md: -------------------------------------------------------------------------------- 1 | # Unit Testing & Mocking 2 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/README.md: -------------------------------------------------------------------------------- 1 | # Ламбда изрази и Stream API 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-vendored 2 | *.java linguist-vendored=false 3 | -------------------------------------------------------------------------------- /07-io-streams-and-files/README.md: -------------------------------------------------------------------------------- 1 | # Входно-изходни потоци и файлове 2 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/README.md: -------------------------------------------------------------------------------- 1 | # OOP in Java (part I) / Code snippets 2 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/README.md: -------------------------------------------------------------------------------- 1 | # Collections / Code snippets 2 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/snippets/README.md: -------------------------------------------------------------------------------- 1 | # Ламбда изрази и Stream API 2 | -------------------------------------------------------------------------------- /02-oop-in-java-i/README.md: -------------------------------------------------------------------------------- 1 | # Обектно-ориентирано програмиране с Java (част I) 2 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/README.md: -------------------------------------------------------------------------------- 1 | # Обектно-ориентирано програмиране с Java (част II) 2 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/README.md: -------------------------------------------------------------------------------- 1 | # OOP in Java (part II) / Code snippets 2 | -------------------------------------------------------------------------------- /07-io-streams-and-files/snippets/README.md: -------------------------------------------------------------------------------- 1 | # Входно-изходни потоци и файлове 2 | -------------------------------------------------------------------------------- /web/Designer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/web/Designer.png -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/README.md: -------------------------------------------------------------------------------- 1 | # Unit Testing & Mocking / Code snippets 2 | -------------------------------------------------------------------------------- /10-network/README.md: -------------------------------------------------------------------------------- 1 | Многонишково програмиране (част II) и Мрежово програмиране (част I) 2 | -------------------------------------------------------------------------------- /web/fonts/remixicon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/web/fonts/remixicon.ttf -------------------------------------------------------------------------------- /web/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/web/images/favicon.png -------------------------------------------------------------------------------- /web/images/java-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/web/images/java-25.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | ### IntelliJ IDEA ### 4 | .idea 5 | *.iws 6 | *.iml 7 | *.ipr 8 | out/ -------------------------------------------------------------------------------- /web/fonts/remixicon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/web/fonts/remixicon.woff -------------------------------------------------------------------------------- /web/fonts/remixicon.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/web/fonts/remixicon.woff2 -------------------------------------------------------------------------------- /05-generics/snippets/src/GenericRecord.java: -------------------------------------------------------------------------------- 1 | public record GenericRecord(K key, V value) { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /web/images/mjt-on-youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/web/images/mjt-on-youtube.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/records/Point.java: -------------------------------------------------------------------------------- 1 | package records; 2 | 3 | public record Point(int x, int y) { 4 | } 5 | -------------------------------------------------------------------------------- /10-network/snippets/README.md: -------------------------------------------------------------------------------- 1 | # Многонишково програмиране (част II) и Мрежово програмиране (част I) / Code snippets 2 | -------------------------------------------------------------------------------- /09-threads/lab/resources/DECODEME.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lab/resources/DECODEME.png -------------------------------------------------------------------------------- /09-threads/lecture/images/09.1-threads.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.1-threads.jpeg -------------------------------------------------------------------------------- /02-oop-in-java-i/lecture/images/02.1-oop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/02-oop-in-java-i/lecture/images/02.1-oop.jpg -------------------------------------------------------------------------------- /07-io-streams-and-files/lab/resources/car.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lab/resources/car.jpg -------------------------------------------------------------------------------- /09-threads/lab/resources/producer-consumer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lab/resources/producer-consumer.png -------------------------------------------------------------------------------- /09-threads/lecture/images/09.10-deadlock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.10-deadlock.jpg -------------------------------------------------------------------------------- /09-threads/lecture/images/09.8-thread-join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.8-thread-join.png -------------------------------------------------------------------------------- /10-network/lecture/images/10.0-networking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/10-network/lecture/images/10.0-networking.jpg -------------------------------------------------------------------------------- /10-network/lecture/images/10.3-osi-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/10-network/lecture/images/10.3-osi-model.png -------------------------------------------------------------------------------- /10-network/lecture/images/10.4-ipv4-ipv6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/10-network/lecture/images/10.4-ipv4-ipv6.png -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.10-rocket.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.10-rocket.jpg -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.11-array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.11-array.png -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.12-matrix.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.12-matrix.jpg -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.13-funcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.13-funcs.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lab/resources/kitten.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lab/resources/kitten.png -------------------------------------------------------------------------------- /09-threads/lecture/images/09.9-thread-states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.9-thread-states.png -------------------------------------------------------------------------------- /10-network/lecture/images/10.1-client-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/10-network/lecture/images/10.1-client-server.png -------------------------------------------------------------------------------- /10-network/lecture/images/10.2-peer-to-peer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/10-network/lecture/images/10.2-peer-to-peer.jpg -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.8-java-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.8-java-app.png -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.9-variables.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.9-variables.jpg -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.3.0-enums.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.3.0-enums.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.6.0-records.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.6.0-records.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.6.1-sealed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.6.1-sealed.png -------------------------------------------------------------------------------- /05-generics/lecture/images/05.0-java-generics.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/05-generics/lecture/images/05.0-java-generics.jpg -------------------------------------------------------------------------------- /09-threads/lecture/images/09.3-multi-core-cpus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.3-multi-core-cpus.jpg -------------------------------------------------------------------------------- /09-threads/lecture/images/09.4-multithreading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.4-multithreading.png -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.2-vscode-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.2-vscode-logo.jpg -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Car.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.overridings; 2 | 3 | public class Car { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.2-call-stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.2-call-stack.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.3-exceptions.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.3-exceptions.jpeg -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.4-exceptions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.4-exceptions.png -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.1-intellij-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.1-intellij-logo.jpg -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.15-effective-java.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.15-effective-java.jpg -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.3-eclipse-logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.3-eclipse-logo.jpeg -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.4-netbeans-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.4-netbeans-logo.jpg -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.6-jep-per-release.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.6-jep-per-release.png -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.7-hello-world-25.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.7-hello-world-25.jpeg -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.0-stack-vs-heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.0-stack-vs-heap.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.4.0-exceptions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.4.0-exceptions.png -------------------------------------------------------------------------------- /05-generics/lecture/images/05.1-collections-subtypes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/05-generics/lecture/images/05.1-collections-subtypes.png -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/lecture/images/08.1-lambda.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/08-lambdas-and-stream-api/lecture/images/08.1-lambda.jpg -------------------------------------------------------------------------------- /09-threads/lecture/images/09.2-meaning-of-concurrent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.2-meaning-of-concurrent.png -------------------------------------------------------------------------------- /09-threads/lecture/images/09.5-concurrent-parallel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.5-concurrent-parallel.png -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.14-thinking-in-java.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.14-thinking-in-java.jpg -------------------------------------------------------------------------------- /01-intro-to-java/lecture/images/01.5-java-logo-mascot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/01-intro-to-java/lecture/images/01.5-java-logo-mascot.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.1-io-streams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.1-io-streams.png -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Audi.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.overridings; 2 | 3 | public class Audi extends Car { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.6-sealed-hierarchy-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.6-sealed-hierarchy-1.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.6-sealed-hierarchy-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.6-sealed-hierarchy-2.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.6-sealed-hierarchy-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.6-sealed-hierarchy-3.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.6-sealed-hierarchy-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.6-sealed-hierarchy-4.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.5-clean-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.5-clean-code.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.6-collections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.6-collections.png -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lecture/images/06.5-mockito.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/06-unit-testing-and-mocking/lecture/images/06.5-mockito.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.2-java-app-io.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.2-java-app-io.png -------------------------------------------------------------------------------- /09-threads/lecture/images/09.6-platform-virtual-threads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.6-platform-virtual-threads.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.14-cheat-sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.14-cheat-sheet.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.2-wtfs-per-min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.2-wtfs-per-min.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.3-oracle-google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.3-oracle-google.png -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lecture/images/06.3-more-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/06-unit-testing-and-mocking/lecture/images/06.3-more-tests.png -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lecture/images/06.4-junit-logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/06-unit-testing-and-mocking/lecture/images/06.4-junit-logo.jpeg -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.10-io-apis-wrapup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.10-io-apis-wrapup.gif -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.5-java-io-classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.5-java-io-classes.png -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/lecture/images/08.0-where-are-we.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/08-lambdas-and-stream-api/lecture/images/08.0-where-are-we.png -------------------------------------------------------------------------------- /10-network/lecture/images/09.6-java-concurrency-in-practice.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/10-network/lecture/images/09.6-java-concurrency-in-practice.jpg -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Likeable.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.adorable; 2 | 3 | interface Likeable { 4 | 5 | void like(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Lovable.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.adorable; 2 | 3 | interface Lovable { 4 | 5 | void love(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.1-clean-code-zen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.1-clean-code-zen.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.10-listperformance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.10-listperformance.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.12-setperformance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.12-setperformance.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.12.0-linkedhashset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.12.0-linkedhashset.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.13-mapperformance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.13-mapperformance.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.7.1-big-o-chart.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.7.1-big-o-chart.jpeg -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lecture/images/06.1-relative-cost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/06-unit-testing-and-mocking/lecture/images/06.1-relative-cost.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.11-java-io-nio-nio2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.11-java-io-nio-nio2.png -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/lecture/images/08.3-variance-formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/08-lambdas-and-stream-api/lecture/images/08.3-variance-formula.png -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/lecture/images/08.6-z-score-formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/08-lambdas-and-stream-api/lecture/images/08.6-z-score-formula.png -------------------------------------------------------------------------------- /09-threads/lecture/images/09.11-java-concurrency-in-practice.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.11-java-concurrency-in-practice.jpg -------------------------------------------------------------------------------- /09-threads/lecture/images/09.7-virtual-threads-sharing-carrier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/09-threads/lecture/images/09.7-virtual-threads-sharing-carrier.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.1-favorite-new-java-features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.1-favorite-new-java-features.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.11-queueperformance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.11-queueperformance.png -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lecture/images/06.2-testing-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/06-unit-testing-and-mocking/lecture/images/06.2-testing-process.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.8-wrapping-io-streams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.8-wrapping-io-streams.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.4-static-code-analyzers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.4-static-code-analyzers.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.7-basic-data-structures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.7-basic-data-structures.png -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/collections/permissions/Permission.java: -------------------------------------------------------------------------------- 1 | package collections.permissions; 2 | 3 | public enum Permission { 4 | READ, WRITE, EXECUTE, DELETE 5 | } 6 | -------------------------------------------------------------------------------- /05-generics/lecture/images/05.2-o-reilly-generics-and-collections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/05-generics/lecture/images/05.2-o-reilly-generics-and-collections.png -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/src/bg/sofia/uni/fmi/mjt/exchange/Currency.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.exchange; 2 | 3 | public enum Currency { 4 | EUR, USD, GBP, BGN 5 | } 6 | -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.12-maserati-edge-detected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.12-maserati-edge-detected.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.4-java-io-class-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.4-java-io-class-hierarchy.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.8.1-standard-io-streams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.8.1-standard-io-streams.png -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/lecture/images/08.4-average-value-formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/08-lambdas-and-stream-api/lecture/images/08.4-average-value-formula.png -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/images/03.5-checked-vs-runtime-exceptions.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/03-oop-in-java-ii/lecture/images/03.5-checked-vs-runtime-exceptions.jpeg -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.5.1-planetgeek-cheatsheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.5.1-planetgeek-cheatsheet.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.7.2-complexity-cheatsheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.7.2-complexity-cheatsheet.png -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/images/04.8-collections-map-hierarchy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/04-collections-clean-code/lecture/images/04.8-collections-map-hierarchy.jpg -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lecture/images/06.0-unit-testing-and-mocking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/06-unit-testing-and-mocking/lecture/images/06.0-unit-testing-and-mocking.png -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lecture/images/06.6-practical-unit-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/06-unit-testing-and-mocking/lecture/images/06.6-practical-unit-testing.png -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/lecture/images/08.2-stream-operations-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/08-lambdas-and-stream-api/lecture/images/08.2-stream-operations-pipeline.png -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/lecture/images/08.5-standard-deviation-formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/08-lambdas-and-stream-api/lecture/images/08.5-standard-deviation-formula.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.3-java-io-root-abstract-classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.3-java-io-root-abstract-classes.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.6-java-byte-io-classes-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.6-java-byte-io-classes-hierarchy.png -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/images/07.7-java-char-io-classes-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fmi/java-course/HEAD/07-io-streams-and-files/lecture/images/07.7-java-char-io-classes-hierarchy.png -------------------------------------------------------------------------------- /05-generics/snippets/src/ExoticFruit.java: -------------------------------------------------------------------------------- 1 | final class Pineapple extends ExoticFruit {} 2 | final class Melon extends ExoticFruit {} 3 | 4 | public sealed class ExoticFruit permits Pineapple, Melon { 5 | private T t; 6 | } 7 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/snippets/src/bg/sofia/uni/fmi/mjt/employees/Employee.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.employees; 2 | 3 | public record Employee(int id, String name, int age, double salary, double bonus) { 4 | } 5 | 6 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/src/bg/sofia/uni/fmi/mjt/math/Calc.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.math; 2 | 3 | public class Calc { 4 | 5 | public int multiply(int a, int b) { 6 | return a * b; 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/OldLockable.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.lockable; 2 | 3 | public interface OldLockable { 4 | 5 | default boolean isLocked() { 6 | return true; 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/interfaces/Bookable.java: -------------------------------------------------------------------------------- 1 | package exceptions.interfaces; 2 | 3 | import java.io.IOException; 4 | 5 | public interface Bookable { 6 | 7 | boolean book(String request) throws IOException; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/sealed/Exercise.java: -------------------------------------------------------------------------------- 1 | package sealed; 2 | 3 | // remove Swimming from the permits clause to break compilation 4 | public sealed interface Exercise permits GymWorkout, Jogging, Swimming { 5 | 6 | int getCaloriesBurnt(); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/EmailNotFoundException.java: -------------------------------------------------------------------------------- 1 | package exceptions; 2 | 3 | public class EmailNotFoundException extends AuthenticationException { 4 | 5 | public EmailNotFoundException() { 6 | super("Email not found"); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/WrongPasswordException.java: -------------------------------------------------------------------------------- 1 | package exceptions; 2 | 3 | public class WrongPasswordException extends AuthenticationException { 4 | 5 | public WrongPasswordException() { 6 | super("Wrong password"); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/records/PointDemo.java: -------------------------------------------------------------------------------- 1 | package records; 2 | 3 | public class PointDemo { 4 | 5 | public static void main(String[] args) { 6 | Point p = new Point(-1, 2); 7 | System.out.println(p.x() + ", " + p.y()); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/AbstractCoolPerson.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.adorable; 2 | 3 | public abstract class AbstractCoolPerson implements Adorable { 4 | 5 | // We are not required to implement the methods in an abstract class. 6 | 7 | } 8 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/src/bg/sofia/uni/fmi/mjt/exchange/CurrencyConverter.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.exchange; 2 | 3 | public interface CurrencyConverter { 4 | 5 | double getExchangeRate(Currency from, Currency to) throws UnknownCurrencyException; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/sealed/GymWorkout.java: -------------------------------------------------------------------------------- 1 | package sealed; 2 | 3 | public final class GymWorkout implements Exercise { 4 | 5 | private static final int GYM_CALORIES = 700; 6 | 7 | @Override 8 | public int getCaloriesBurnt() { 9 | return GYM_CALORIES; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/sealed/Jogging.java: -------------------------------------------------------------------------------- 1 | package sealed; 2 | 3 | public non-sealed class Jogging implements Exercise { 4 | 5 | private static final int JOGGING_CALORIES = 450; 6 | 7 | @Override 8 | public int getCaloriesBurnt() { 9 | return JOGGING_CALORIES; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/signature/ExceptionSignatureBase.java: -------------------------------------------------------------------------------- 1 | package exceptions.signature; 2 | 3 | import java.io.IOException; 4 | 5 | public class ExceptionSignatureBase { 6 | 7 | public void fun(String s) throws MyExceptionBase { 8 | 9 | } 10 | 11 | } 12 | 13 | class MyExceptionBase extends IOException { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /05-generics/snippets/src/Container.java: -------------------------------------------------------------------------------- 1 | public class Container { 2 | 3 | public static void main(String[] args) { 4 | Container ci = new Container<>(); 5 | Container cd = new Container<>(); 6 | 7 | // Container cs = new Container<>(); // will not compile 8 | 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Door.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.lockable; 2 | 3 | public class Door implements Lockable, OldLockable { 4 | 5 | @Override 6 | public void lock() { 7 | System.out.println("Door locked."); 8 | } 9 | 10 | @Override 11 | public boolean isLocked() { 12 | return true; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Adorable.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.adorable; 2 | 3 | interface Adorable extends Likeable, Lovable { 4 | 5 | // This interface inherits both like() and love() methods and does not define new methods. 6 | // Any class that will implement it, is required to implement both like() and love(), or declare itself as abstract. 7 | 8 | } 9 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/AuthenticationException.java: -------------------------------------------------------------------------------- 1 | package exceptions; 2 | 3 | public class AuthenticationException extends Exception { 4 | 5 | public AuthenticationException(String message) { 6 | super(message); 7 | } 8 | 9 | public AuthenticationException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Vault.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.lockable; 2 | 3 | 4 | public class Vault implements Lockable { 5 | 6 | @Override 7 | public void lock() { 8 | System.out.println("Vault locked with biometric authentication."); 9 | } 10 | 11 | @Override 12 | public boolean isLocked() { 13 | return true; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/records/Order.java: -------------------------------------------------------------------------------- 1 | package records; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | public record Order(int id, String username, LocalDateTime timestamp) { 6 | private static int order_id; 7 | 8 | static { 9 | order_id = 0; 10 | } 11 | 12 | public static Order of(String username) { 13 | return new Order(++order_id, username, LocalDateTime.now()); 14 | } 15 | } -------------------------------------------------------------------------------- /01-intro-to-java/snippets/UnnamedClassesExample.java: -------------------------------------------------------------------------------- 1 | // NOTE: This is possible thanks to preview language features in Java 21 and 23. 2 | 3 | // No class declaration is required 4 | // Java keywords public and static are no longer required for main 5 | // Main method argument args is optional 6 | // The static methods of java.io.IO such as println() are automatically imported 7 | void main() { 8 | println("Hello, World!"); 9 | } 10 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/comparators/CarByBrandComparator.java: -------------------------------------------------------------------------------- 1 | package comparators; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Comparator that sorts cars alphabetically by brand name. 7 | */ 8 | public class CarByBrandComparator implements Comparator { 9 | 10 | @Override 11 | public int compare(Car a, Car b) { 12 | return a.getBrand().compareTo(b.getBrand()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/file/exception/EmptyFileException.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.file.exception; 2 | 3 | public class EmptyFileException extends RuntimeException { 4 | 5 | public EmptyFileException(String message) { 6 | super(message); 7 | } 8 | 9 | public EmptyFileException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/src/bg/sofia/uni/fmi/mjt/exchange/UnknownCurrencyException.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.exchange; 2 | 3 | public class UnknownCurrencyException extends Exception { 4 | 5 | public UnknownCurrencyException(String message) { 6 | super(message); 7 | } 8 | 9 | public UnknownCurrencyException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/comparators/CarByTopSpeedDescComparator.java: -------------------------------------------------------------------------------- 1 | package comparators; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Comparator that sorts cars by top speed in descending order. 7 | */ 8 | public class CarByTopSpeedDescComparator implements Comparator { 9 | 10 | @Override 11 | public int compare(Car a, Car b) { 12 | return Integer.compare(b.getTopSpeed(), a.getTopSpeed()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/signature/ExceptionSignature.java: -------------------------------------------------------------------------------- 1 | package exceptions.signature; 2 | 3 | public class ExceptionSignature extends ExceptionSignatureBase { 4 | 5 | @Override 6 | public void fun(String s) throws MyException { 7 | try { 8 | super.fun(s); 9 | } catch (MyExceptionBase e) { 10 | throw new RuntimeException(e); 11 | } 12 | } 13 | 14 | } 15 | 16 | class MyException extends MyExceptionBase { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Домашни 2 | 3 | | # | Условие | Краен срок | 4 | |:--|:----------------------------------------------------------------------------------------- |:---------------- | 5 | | 1 | [JobMatch](https://github.com/fmi/java-course/tree/master/homeworks/01-jobmatch) | 26.11.2025 23:59 | 6 | | 2 | [Space Scanner](https://github.com/fmi/java-course/tree/master/homeworks/02-spacescanner) | 22.12.2023 23:59 | 7 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/src/bg/sofia/uni/fmi/mjt/exchange/GoogleCurrencyConverter.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.exchange; 2 | 3 | import java.net.URL; 4 | 5 | public class GoogleCurrencyConverter implements CurrencyConverter { 6 | 7 | public GoogleCurrencyConverter(URL webServiceEndpoint, String user, String password) { 8 | // some complex logic here 9 | } 10 | 11 | @Override 12 | public double getExchangeRate(Currency from, Currency to) { 13 | return 0.0; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/HelpfulNPE.java: -------------------------------------------------------------------------------- 1 | package exceptions; 2 | 3 | public class HelpfulNPE { 4 | 5 | public static void main(String[] args) { 6 | new HelpfulNPE().helpfulNPEdemo(); 7 | } 8 | 9 | public void helpfulNPEdemo() { 10 | A a = new A(); 11 | a.b.c.number = 100; 12 | } 13 | 14 | class A { 15 | public B b; 16 | } 17 | 18 | class B { 19 | public C c; 20 | } 21 | 22 | class C { 23 | public int number; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/records/OrderDemo.java: -------------------------------------------------------------------------------- 1 | package records; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | public class OrderDemo { 6 | public static void main(String[] args) throws InterruptedException { 7 | Order o1 = Order.of("Misho"); 8 | Thread.sleep(1000); 9 | Order o2 = Order.of("Desi"); 10 | Thread.sleep(2000); 11 | Order o3 = Order.of("Stoyo"); 12 | 13 | System.out.println(o1); 14 | System.out.println(o2); 15 | System.out.println(o3); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/src/bg/sofia/uni/fmi/mjt/exchange/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.exchange; 2 | 3 | public class CurrencyExchange { 4 | 5 | private CurrencyConverter converter; 6 | 7 | public CurrencyExchange(CurrencyConverter converter) { 8 | this.converter = converter; 9 | } 10 | 11 | public double exchangeSum(Currency from, Currency to, double fromAmount) throws UnknownCurrencyException { 12 | return fromAmount * converter.getExchangeRate(from, to); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /09-threads/snippets/src/Depositor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Thread will simply iterate n times and deposit 1 3 | * into a shared account 4 | */ 5 | public class Depositor extends Thread { 6 | private BankAccount account; 7 | private int attempts; 8 | 9 | public Depositor(BankAccount account, int attempts) { 10 | this.account = account; 11 | this.attempts = attempts; 12 | } 13 | 14 | @Override 15 | public void run() { 16 | for (int i = 0; i < attempts; i++) { 17 | account.deposit(1); 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/argumentpassing/PrimitiveArgumentsExample.java: -------------------------------------------------------------------------------- 1 | package argumentpassing; 2 | 3 | public class PrimitiveArgumentsExample { 4 | 5 | public static void main(String[] args) { 6 | int x = 10; 7 | System.out.println("Before modifyPrimitive: " + x); 8 | 9 | modifyPrimitive(x); 10 | 11 | System.out.println("After modifyPrimitive: " + x); 12 | } 13 | 14 | public static void modifyPrimitive(int number) { 15 | number = 20; 16 | System.out.println("Inside method: " + number); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/CoolPerson.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.adorable; 2 | 3 | public class CoolPerson implements Adorable { 4 | // If we do not implement all Adorable methods, we will get a compile-time error: 5 | // "CoolPerson is not abstract and does not override abstract method like() in Likeable" 6 | 7 | @Override 8 | public void like() { 9 | System.out.println("I am liked!"); 10 | } 11 | 12 | @Override 13 | public void love() { 14 | System.out.println("I am loved!"); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /10-network/snippets/src/threadpools/Task.java: -------------------------------------------------------------------------------- 1 | package threadpools; 2 | 3 | public class Task implements Runnable { 4 | private final String taskId; 5 | 6 | public Task(String id) { 7 | this.taskId = id; 8 | } 9 | 10 | @Override 11 | public void run() { 12 | System.out.println("Executing Task Id: " + taskId + ", by " + Thread.currentThread().getName()); 13 | try { 14 | Thread.sleep(1_000); // Simulate some work with a sleep. 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Safe.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.lockable; 2 | 3 | public class Safe implements Lockable, OldLockable { 4 | 5 | @Override 6 | public void lock() { 7 | System.out.println("Safe locked."); 8 | } 9 | 10 | @Override 11 | public boolean isLocked() { 12 | // We will get a compile-time error, if we don't override the isLocked() method here: 13 | // - "Safe inherits unrelated defaults for isLocked() from types Lockable and OldLockable" 14 | return Lockable.super.isLocked(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Garage.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.overridings; 2 | 3 | public class Garage { 4 | 5 | public Garage() { 6 | System.out.println("Garage constructed"); 7 | } 8 | 9 | protected Car repair(Car c) { 10 | return new Car(); 11 | } 12 | 13 | public Car repair(Car c, String customerName) { 14 | // overloaded method: 15 | // 1. access modifier may be any 16 | // 2. return type may be any 17 | // 3. name should be identical 18 | // 4. parameter list should be different 19 | return this.repair(c); // "this." is optional here 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/enums/Day.java: -------------------------------------------------------------------------------- 1 | package enums; 2 | 3 | // Enums extend the java.lang.Enum class implicitly. 4 | // Therefore, you cannot extend any other class in enum. 5 | public enum Day { 6 | 7 | SUNDAY("Sun."), MONDAY("Mon."), TUESDAY("Tue."), WEDNESDAY("Wed."), THURSDAY("Thu."), FRIDAY("Fri."), SATURDAY("Sat."); 8 | 9 | private final String abbreviation; 10 | 11 | // Constructor is always private or default. 12 | // You cannot create an instance of enum using the new operator. 13 | Day(String abbreviation) { 14 | this.abbreviation = abbreviation; 15 | } 16 | 17 | public String getAbbreviation() { 18 | return abbreviation; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/src/bg/sofia/uni/fmi/mjt/math/NumberUtils.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.math; 2 | 3 | public class NumberUtils { 4 | 5 | public static boolean isPrime(int n) { 6 | 7 | if (n < 2) { 8 | throw new IllegalArgumentException("Number not in the domain of function"); 9 | } 10 | 11 | if (n == 2) { 12 | return true; 13 | } 14 | 15 | if (n % 2 == 0) { 16 | return false; 17 | } 18 | 19 | for (int i = 3; i <= Math.sqrt(n); i++) { 20 | if (n % i == 0) { 21 | return false; 22 | } 23 | } 24 | 25 | return true; 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/interfaces/AirBnB.java: -------------------------------------------------------------------------------- 1 | package exceptions.interfaces; 2 | 3 | import java.io.IOException; 4 | 5 | public class AirBnB implements Bookable { 6 | 7 | @Override 8 | public boolean book(String request) throws IOException { 9 | // 1. An overriding method can throw any unchecked exceptions, regardless of whether the overridden method 10 | // throws exceptions or not. 11 | // 2. The overriding method should not throw checked exceptions that are new or broader 12 | // than the ones declared by the overridden method. 13 | // 3. The overriding method can throw narrower or fewer exceptions than the overridden method. 14 | return true; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/test/bg/sofia/uni/fmi/mjt/math/CalcTest.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.math; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.assertEquals; 6 | 7 | class CalcTest { 8 | 9 | Calc calc = new Calc(); 10 | 11 | @Test 12 | void testMultiplyXByZeroShouldReturnZero() { 13 | assertEquals(0, calc.multiply(10, 0), "10 x 0 must be 0"); 14 | } 15 | 16 | @Test 17 | void testMultiplyZeroByXShouldReturnZero() { 18 | assertEquals(0, calc.multiply(0, 10), "0 x 10 must be 0"); 19 | } 20 | 21 | @Test 22 | void testMultiplyZeroByZeroShouldReturnZero() { 23 | assertEquals(0, calc.multiply(0, 0), "0 x 0 must be 0"); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/file/File.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.file; 2 | 3 | /** 4 | * A simple in-memory representation of a file containing textual content. 5 | */ 6 | public class File { 7 | 8 | private String content; 9 | 10 | /** 11 | * Creates a new File with the given content. 12 | * 13 | * @param content the initial content of the file 14 | * @throws IllegalArgumentException if content is null 15 | */ 16 | public File(String content) { 17 | this.content = content; 18 | } 19 | 20 | public String getContent() { 21 | return content; 22 | } 23 | 24 | public void setContent(String content) { 25 | this.content = content; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /playground/02-dna-analyzer/SampleDNAAnalyzerTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.jupiter.api.BeforeAll; 2 | import org.junit.jupiter.api.Test; 3 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | 6 | public class SampleDNAAnalyzerTest { 7 | 8 | private static DNAAnalyzer dnaAnalyzer; 9 | 10 | @BeforeAll 11 | public static void setUp() { 12 | dnaAnalyzer = new DNAAnalyzer(); 13 | } 14 | 15 | @Test 16 | public void testDNAAnalyzer_Abracadabra() { 17 | assertEquals("abra", dnaAnalyzer.longestRepeatingSequence("abracadabra")); 18 | } 19 | 20 | @Test 21 | public void testDNAAnalyzer_DNASequence() { 22 | assertEquals("TACTC", dnaAnalyzer.longestRepeatingSequence("ATACTCGGTACTCT")); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Lockable.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.lockable; 2 | 3 | public interface Lockable { 4 | 5 | void lock(); 6 | 7 | default boolean isLocked() { 8 | return false; 9 | } 10 | 11 | // Static factory method: typical use of static methods in interfaces. 12 | // Keep calm - will learn what Factory is in the Design Patterns lecture 13 | static Lockable of(String type) { 14 | switch (type.toLowerCase()) { 15 | case "door": 16 | return new Door(); 17 | case "safe": 18 | return new Safe(); 19 | case "vault": 20 | return new Vault(); 21 | default: 22 | return null; 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/pipeline/step/Step.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.pipeline.step; 2 | 3 | /** 4 | * Represents a single processing step in a pipeline. 5 | *

6 | * Each step transforms input of type {@code I} into output of type {@code O}. 7 | * Implementations should provide the transformation logic in the {@link #process(Object)} 8 | * method. 9 | * 10 | * @param the type of input the step accepts 11 | * @param the type of output the step produces 12 | */ 13 | public interface Step { 14 | 15 | /** 16 | * Processes the given input and produces an output. 17 | * 18 | * @param input the input data to process 19 | * @return the output data produced by this step 20 | */ 21 | O process(I input); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/sealed/Swimming.java: -------------------------------------------------------------------------------- 1 | package sealed; 2 | 3 | // the compilation failure here is intended - 'Swimming' is not allowed in the sealed hierarchy of Exercise 4 | sealed class Swimming implements Exercise { 5 | 6 | private static final int SWIMMING_CALORIES = 650; 7 | 8 | @Override 9 | public int getCaloriesBurnt() { 10 | return SWIMMING_CALORIES; 11 | } 12 | 13 | } 14 | 15 | // Note that any subclasses of a sealed class defined in the same source file 16 | // need not be mentioned in a permits clause of their parent 17 | final class OceanSwimming extends Swimming { 18 | 19 | private static final int OCEAN_SWIMMING_CALORIES = 700; 20 | 21 | @Override 22 | public int getCaloriesBurnt() { 23 | return OCEAN_SWIMMING_CALORIES; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /07-io-streams-and-files/snippets/src/bg/sofia/uni/fmi/mjt/io/Student.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.io; 2 | 3 | import java.io.Serial; 4 | import java.io.Serializable; 5 | 6 | public class Student implements Serializable { 7 | 8 | // Serialization will not work the same for a record: 9 | // the serialVersionUID will be ignored. 10 | // The @Serial annotation is introduced in Java 14. 11 | 12 | @Serial 13 | private static final long serialVersionUID = -7737678883550377070L; 14 | 15 | String name; 16 | int age; 17 | 18 | public Student(String name, int age) { 19 | this.name = name; 20 | this.age = age; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public int getAge() { 28 | return age; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/collections/permissions/PermissionTracker.java: -------------------------------------------------------------------------------- 1 | package collections.permissions; 2 | 3 | import java.util.EnumMap; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | public class PermissionTracker { 8 | private final EnumMap> usersByPermission = new EnumMap<>(Permission.class); 9 | 10 | public PermissionTracker() { 11 | for (Permission p : Permission.values()) { 12 | usersByPermission.put(p, new HashSet<>()); 13 | } 14 | } 15 | 16 | public void registerUser(User user) { 17 | for (Permission p : user.getPermissions()) { 18 | usersByPermission.get(p).add(user); 19 | } 20 | } 21 | 22 | public Set getUsersWithPermission(Permission permission) { 23 | return usersByPermission.get(permission); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /playground/README.md: -------------------------------------------------------------------------------- 1 | # Playground :video_game: 2 | 3 | В тази секция има допълнителни бонус задачи, с които да премериш сили. В общия случай, те са малко по-сложни, но за сметка на това, често са най-интригуващи. Тук добавяме и любимите ни задачи от предни издания на курса. 4 | 5 | | # | Задача | Какво тренира | 6 | |:--:|:--------------------- |:--------------------| 7 | | 01 | [Stock Exchange](https://github.com/fmi/java-course/tree/master/playground/01-stock-exchange) | масиви, цикли, алгоритми | 8 | | 02 | [DNA Analyzer](https://github.com/fmi/java-course/tree/master/playground/02-dna-analyzer) | низове, цикли, алгоритми | 9 | | 03 | [Dungeons](https://github.com/fmi/java-course/tree/master/playground/03-dungeons) | ООП, низове, цикли | 10 | | 04 | [Cryptic Letter](https://github.com/fmi/java-course/tree/master/playground/04-cryptic-letter) | низове, цикли | 11 | -------------------------------------------------------------------------------- /10-network/snippets/src/network/InetAddressExample.java: -------------------------------------------------------------------------------- 1 | void main() throws IOException { 2 | 3 | InetAddress address = InetAddress.getByName("www.google.com"); 4 | IO.println(address.getHostAddress()); // 172.217.17.132 5 | 6 | address = InetAddress.getByName("62.44.101.151"); 7 | IO.println(address.getHostName()); // learn.fmi.uni-sofia.bg 8 | 9 | IO.println(address.isReachable(5_000)); // true 10 | 11 | InetAddress localhost = InetAddress.getLocalHost(); 12 | IO.println(localhost.getHostAddress()); // IP associated with your hostname, 13 | // typically LAN IP (192.168.x.x) 14 | 15 | // Think of: 16 | // - LAN IP = your apartment number 17 | // - Public IP = the street address for the whole building 18 | // - 127.0.0.1 = your own room inside your apartment (only you can reach it) 19 | 20 | } 21 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/file/step/CountFiles.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.file.step; 2 | 3 | import java.util.Collection; 4 | import bg.sofia.uni.fmi.mjt.file.File; 5 | import bg.sofia.uni.fmi.mjt.pipeline.step.Step; 6 | 7 | /** 8 | * A pipeline step that counts the number of {@link File} objects in a collection. 9 | */ 10 | public class CountFiles implements Step, Integer> { 11 | 12 | /** 13 | * Returns the number of {@link File} objects in the input collection. 14 | * 15 | * @param input the collection of files to count; 16 | * @return the number of files in the collection 17 | * 18 | * @throws IllegalArgumentException if the input collection is null 19 | */ 20 | @Override 21 | public Integer process(Collection input) { 22 | return input.size(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/exceptions/SmartNPEExample.java: -------------------------------------------------------------------------------- 1 | package exceptions; 2 | 3 | class Human { 4 | private String name; 5 | 6 | public Human(String name) { 7 | this.name = name; 8 | } 9 | 10 | public String getName() { 11 | return name; 12 | } 13 | } 14 | 15 | class Student extends Human { 16 | int facultyNumber; 17 | 18 | public Student(String name, int facultyNumber) { 19 | super(name); 20 | this.facultyNumber = facultyNumber; 21 | } 22 | 23 | } 24 | 25 | public class SmartNPEExample { 26 | 27 | public static void main(String[] args) { 28 | Student student1 = new Student("Pancho", 62438); 29 | Student student2 = new Student(null, 45689); 30 | 31 | System.out.println(student1.getName().startsWith("P")); 32 | System.out.println(student2.getName().startsWith("P")); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /playground/01-stock-exchange/SampleStockExchangeTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.BeforeClass; 2 | import org.junit.Test; 3 | 4 | import static org.junit.Assert.assertEquals; 5 | 6 | public class SampleStockExchangeTest { 7 | 8 | private static StockExchange stockExchange; 9 | 10 | @BeforeClass 11 | public static void setUp() { 12 | stockExchange = new StockExchange(); 13 | } 14 | 15 | @Test 16 | public void testStockExchange_StockOne() { 17 | assertEquals(stockExchange.maxProfit(new int[]{7, 1, 5, 3, 6, 4}), 7); 18 | } 19 | 20 | @Test 21 | public void testStockExchange_StockTwo() { 22 | assertEquals(stockExchange.maxProfit(new int[]{1, 2, 3, 4, 5}), 4); 23 | } 24 | 25 | @Test 26 | public void testStockExchange_StockThree() { 27 | assertEquals(stockExchange.maxProfit(new int[]{7, 6, 4, 3, 1}), 0); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /09-threads/snippets/src/JoinExample.java: -------------------------------------------------------------------------------- 1 | public class JoinExample { 2 | 3 | static void main() { 4 | TimerBomb bomb = new TimerBomb(); 5 | bomb.start(); 6 | 7 | // Main thread will wait until bomb thread finishes 8 | try { 9 | bomb.join(); 10 | } catch (InterruptedException e) { 11 | // Should not happen 12 | } 13 | 14 | System.out.println("BOOOOOM!"); 15 | } 16 | 17 | } 18 | 19 | class TimerBomb extends Thread { 20 | private String[] count = {"five", "four", "three", "two", "one"}; 21 | 22 | @Override 23 | public void run() { 24 | for (String c : count) { 25 | System.out.println(c); 26 | 27 | try { 28 | Thread.sleep(1_500); 29 | } catch (InterruptedException e) { 30 | throw new RuntimeException(e); 31 | } 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /09-threads/snippets/src/DaemonThreads.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Daemon threads sample 3 | */ 4 | public class DaemonThreads { 5 | 6 | static void main() throws InterruptedException { 7 | BackgroundTask backgroundTask = new BackgroundTask(); 8 | backgroundTask.start(); 9 | 10 | System.out.println("Main thread terminates"); 11 | } 12 | 13 | } 14 | 15 | /** 16 | * The thread will count to 1000 in the background. 17 | */ 18 | class BackgroundTask extends Thread { 19 | public BackgroundTask() { 20 | // if you comment next line, thread will 21 | // be non-daemon and will always reach to the end and exit normally 22 | setDaemon(true); 23 | } 24 | 25 | @Override 26 | public void run() { 27 | for (int i = 0; i < 1_000; i++) { 28 | System.out.println(i); 29 | } 30 | System.out.printf("%s thread terminates", (isDaemon() ? "Daemon" : "Non-daemon")); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/AudiGarage.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.overridings; 2 | 3 | public class AudiGarage extends Garage { 4 | 5 | public AudiGarage() { 6 | // Note that parent default constructor will be invoked prior to this one. 7 | // Calling it explicitly with super() here will have the same effect 8 | System.out.println("Audi garage constructed"); 9 | } 10 | 11 | public static void main(String... args) { // varargs syntax 12 | new AudiGarage(); 13 | } 14 | 15 | @Override 16 | public Audi repair(Car c) { 17 | // 1. access modifier upgraded from protected to public. Trying to reduce it to private will not compile 18 | // 2. covariant return type: overriden method in parent returns Car 19 | // 3. signature remains identical: otherwise, with the @Override annotation in place, will not compile 20 | return new Audi(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /07-io-streams-and-files/snippets/test/TempFileTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.jupiter.api.Test; 2 | import org.junit.jupiter.api.io.TempDir; 3 | 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | 7 | import static org.junit.jupiter.api.Assertions.*; 8 | 9 | class TempFileTest { 10 | 11 | @Test 12 | void tempFileExample(@TempDir Path tempDir) throws Exception { 13 | 14 | System.out.println("Auto created temporary directory: " + tempDir); 15 | 16 | // Създаваме файл във временната директория 17 | // с Files.createFile(...) или Path.resolve(...) 18 | Path file = tempDir.resolve("sample.txt"); 19 | 20 | Files.writeString(file, "Hello from JUnit 6!"); 21 | 22 | String text = Files.readString(file); 23 | 24 | assertEquals("Hello from JUnit 6!", text, "Unexpected file content"); 25 | 26 | // Временната директория ще се изттрие автоматично след теста, 27 | // заедно със съдържанието си. 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /09-threads/snippets/src/RaceConditionExample.java: -------------------------------------------------------------------------------- 1 | public class RaceConditionExample { 2 | 3 | static void main() throws Exception { 4 | // Shared bank account 5 | BankAccount acc = new BankAccount("Anonymous"); 6 | BankAccount acc2 = new BankAccount("Second..."); 7 | 8 | // Many threads will concurrently deposit money into the same account 9 | Depositor[] depositors = new Depositor[100]; 10 | for (int i = 0; i < depositors.length; i++) { 11 | depositors[i] = new Depositor(acc, 500); 12 | depositors[i].start(); 13 | } 14 | 15 | // Main thread will wait until all depositors are done. 16 | for (int i = 0; i < depositors.length; i++) { 17 | depositors[i].join(); 18 | } 19 | 20 | // Result should be consistent, if BankAccount is thread-safe 21 | System.out.println(acc); 22 | System.out.println("Operations: " + BankAccount.getOpCount()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/file/step/UpperCaseFile.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.file.step; 2 | 3 | import bg.sofia.uni.fmi.mjt.file.File; 4 | import bg.sofia.uni.fmi.mjt.pipeline.step.Step; 5 | 6 | /** 7 | * A pipeline step that transforms the content of a {@link File} to uppercase. 8 | *

9 | * This step modifies the {@link File} in place by converting its content 10 | * to uppercase. 11 | */ 12 | public class UpperCaseFile implements Step { 13 | 14 | /** 15 | * Converts the content of the given {@link File} to uppercase. 16 | * 17 | * @param input the file whose content will be transformed 18 | * @return a new {@link File} object with updated content 19 | * 20 | * @throws IllegalArgumentException if the input file or its content is null 21 | */ 22 | @Override 23 | public File process(File input) { 24 | input.getContent().toUpperCase(); 25 | return input; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /10-network/snippets/src/network/LanIpFinder.java: -------------------------------------------------------------------------------- 1 | void main() throws Exception { 2 | InetAddress lanIp = getLanIp(); 3 | IO.println(lanIp); 4 | } 5 | 6 | public static InetAddress getLanIp() throws SocketException { 7 | Enumeration nics = NetworkInterface.getNetworkInterfaces(); 8 | 9 | while (nics.hasMoreElements()) { 10 | NetworkInterface nic = nics.nextElement(); 11 | 12 | // Skip loopback, down, or virtual interfaces 13 | if (!nic.isUp() || nic.isLoopback() || nic.isVirtual()) { 14 | continue; 15 | } 16 | 17 | Enumeration addrs = nic.getInetAddresses(); 18 | while (addrs.hasMoreElements()) { 19 | InetAddress addr = addrs.nextElement(); 20 | 21 | // We want only IPv4 addresses and exclude loopback 22 | if (addr instanceof Inet4Address && !addr.isLoopbackAddress()) { 23 | return addr; 24 | } 25 | } 26 | } 27 | return null; // or throw exception if required 28 | } 29 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/enums/StringConstants.java: -------------------------------------------------------------------------------- 1 | package enums; 2 | 3 | public class StringConstants { 4 | 5 | // 1. This approach can lead to performance problems because it relies on string comparisons 6 | // 2. If the constants contain typos, they will escape detection at compile time and result in bugs at runtime 7 | // 3. There is no way to iterate over all enumerated types 8 | // 4. There is no type safety 9 | public static final String MONDAY = "monday"; 10 | public static final String TUESDAY = "tuesday"; 11 | public static final String WEDNESDAY = "wednesday"; 12 | public static final String THURSDAY = "thursday"; 13 | public static final String FRIDAY = "friday"; 14 | public static final String SATURDAY = "saturday"; 15 | public static final String SUNDAY = "sunday"; 16 | 17 | // We can pass whatever we want here, no matter if it is an actual day or not 18 | public static void printDayMessage(String day) { 19 | // Print some message according to the day 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/collections/permissions/EnumCollectionsDemo.java: -------------------------------------------------------------------------------- 1 | package collections.permissions; 2 | 3 | import java.util.EnumSet; 4 | 5 | public class EnumCollectionsDemo { 6 | public static void main(String[] args) { 7 | User alice = new User("Alice", EnumSet.of(Permission.READ, Permission.WRITE)); 8 | User bob = new User("Bob", EnumSet.of(Permission.READ, Permission.EXECUTE)); 9 | User carol = new User("Carol", EnumSet.allOf(Permission.class)); 10 | 11 | PermissionTracker tracker = new PermissionTracker(); 12 | tracker.registerUser(alice); 13 | tracker.registerUser(bob); 14 | tracker.registerUser(carol); 15 | 16 | System.out.println("Users with READ permission: " + tracker.getUsersWithPermission(Permission.READ)); 17 | System.out.println("Users with EXECUTE permission: " + tracker.getUsersWithPermission(Permission.EXECUTE)); 18 | System.out.println("Users with DELETE permission: " + tracker.getUsersWithPermission(Permission.DELETE)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/collections/permissions/User.java: -------------------------------------------------------------------------------- 1 | package collections.permissions; 2 | 3 | import java.util.EnumSet; 4 | 5 | public class User { 6 | private final String username; 7 | private final EnumSet permissions; 8 | 9 | public User(String username, EnumSet permissions) { 10 | this.username = username; 11 | this.permissions = permissions.clone(); // Defensive copy 12 | } 13 | 14 | public boolean hasPermission(Permission permission) { 15 | return permissions.contains(permission); 16 | } 17 | 18 | public void grantPermission(Permission permission) { 19 | permissions.add(permission); 20 | } 21 | 22 | public void revokePermission(Permission permission) { 23 | permissions.remove(permission); 24 | } 25 | 26 | public EnumSet getPermissions() { 27 | return permissions.clone(); 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return username + ": " + permissions; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/suuper/SuperExample.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.suuper; 2 | 3 | class Parent { 4 | int parentValue; 5 | 6 | Parent(int parentValue) { 7 | this.parentValue = parentValue; 8 | } 9 | 10 | void displayParent() { 11 | System.out.println("Parent value: " + parentValue); 12 | } 13 | } 14 | 15 | class Child extends Parent { 16 | int childValue; 17 | 18 | Child(int parentValue, int childValue) { 19 | super(parentValue); // Call the superclass constructor 20 | this.childValue = childValue; 21 | } 22 | 23 | void displayChild() { 24 | System.out.println("Child value: " + childValue); 25 | } 26 | 27 | void displayParentAndChild() { 28 | super.displayParent(); // Call the parent class method using super 29 | displayChild(); 30 | } 31 | } 32 | 33 | public class SuperExample { 34 | public static void main(String[] args) { 35 | Child child = new Child(10, 20); 36 | 37 | child.displayParentAndChild(); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /10-network/snippets/src/threadpools/CachedThreadPoolExample.java: -------------------------------------------------------------------------------- 1 | package threadpools; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class CachedThreadPoolExample { 7 | 8 | // A cached thread pool will reuse available threads, but if all threads are busy 9 | // and more tasks are submitted, it will create new threads. 10 | // If a thread is idle for 60s, it will be decommissioned. 11 | 12 | private static final int MAX_TASKS = 15; 13 | 14 | static void main() { 15 | 16 | // Creates a thread pool with a fixed number of threads 17 | ExecutorService executor = Executors.newCachedThreadPool(); 18 | 19 | // Submit tasks to the executor. 20 | for (int i = 0; i < MAX_TASKS; i++) { 21 | Runnable task = new Task("" + i); 22 | executor.execute(task); // Execute the task using the thread pool. 23 | } 24 | 25 | // Shutdown the executor service. It will not accept new tasks but complete existing ones. 26 | executor.shutdown(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /10-network/snippets/src/threadpools/FixedThreadPoolExample.java: -------------------------------------------------------------------------------- 1 | package threadpools; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class FixedThreadPoolExample { 7 | 8 | // A fixed thread pool contains a specified number of threads. If all threads are busy 9 | // and additional tasks are submitted, they will wait in the queue until a thread is available. 10 | 11 | private static final int MAX_THREADS = 3; 12 | private static final int MAX_TASKS = 15; 13 | 14 | static void main() { 15 | 16 | // Creates a thread pool with a fixed number of threads 17 | ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS); 18 | 19 | // Submit tasks to the executor. 20 | for (int i = 0; i < MAX_TASKS; i++) { 21 | Runnable task = new Task("" + i); 22 | executor.execute(task); // Execute the task using the thread pool. 23 | } 24 | 25 | // Shutdown the executor service. It will not accept new tasks but complete existing ones. 26 | executor.shutdown(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/file/step/CheckEmptyFile.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.file.step; 2 | 3 | import bg.sofia.uni.fmi.mjt.file.File; 4 | import bg.sofia.uni.fmi.mjt.file.exception.EmptyFileException; 5 | import bg.sofia.uni.fmi.mjt.pipeline.step.Step; 6 | 7 | /** 8 | * A pipeline step that validates whether a {@link File} is empty. 9 | */ 10 | public class CheckEmptyFile implements Step { 11 | 12 | /** 13 | * Validates that the input {@link File} is not empty. 14 | * 15 | * @param input the file to check 16 | * @return the same {@link File} if it is not empty 17 | * @throws EmptyFileException with message "Input file or its content is empty or null" 18 | * if the file is null or if the file content 19 | * is empty or null. 20 | */ 21 | @Override 22 | public File process(File input) { 23 | if (input.getContent().isEmpty()) { 24 | throw new IllegalArgumentException("Input file is empty"); 25 | } 26 | 27 | return input; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /09-threads/snippets/src/StaticResourceExample.java: -------------------------------------------------------------------------------- 1 | public class StaticResourceExample { 2 | 3 | static void main() throws Exception { 4 | 5 | // BankAccount of Ivan and Pesho 6 | BankAccount ivanAcc = new BankAccount("Ivan"); 7 | BankAccount peshoAcc = new BankAccount("Pesho"); 8 | 9 | // 10 depositor threads - 5 will deposit to Ivan and 5 to Pesho 10 | Depositor[] depositors = new Depositor[10]; 11 | for (int i = 0; i < depositors.length; i++) { 12 | if (i % 2 == 0) { 13 | depositors[i] = new Depositor(ivanAcc, 1_000); 14 | } else { 15 | depositors[i] = new Depositor(peshoAcc, 1_000); 16 | } 17 | depositors[i].start(); 18 | } 19 | 20 | for (int i = 0; i < depositors.length; i++) { 21 | depositors[i].join(); 22 | } 23 | 24 | // Should be correct 25 | System.out.println(ivanAcc); 26 | System.out.println(peshoAcc); 27 | 28 | // Total ops count should be 10000 29 | System.out.println("Total deposit ops : " + BankAccount.getOpCount()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/collections/scheduler/TaskScheduler.java: -------------------------------------------------------------------------------- 1 | package collections.scheduler; 2 | 3 | import java.util.Comparator; 4 | import java.util.PriorityQueue; 5 | import java.util.Queue; 6 | 7 | public class TaskScheduler { 8 | 9 | public static void main(String[] args) { 10 | Queue queue = new PriorityQueue<>(Comparator.reverseOrder()); 11 | queue.add(new Task("Email", 2)); 12 | queue.add(new Task("Backup", 1)); 13 | queue.add(new Task("Report", 3)); 14 | while (!queue.isEmpty()) { 15 | System.out.println("Next: " + queue.poll()); 16 | } 17 | // Output: Next: Backup(1), Next: Email(2), Next: Report(3) 18 | } 19 | 20 | } 21 | 22 | class Task implements Comparable { 23 | String name; 24 | int priority; 25 | 26 | Task(String name, int priority) { 27 | this.name = name; 28 | this.priority = priority; 29 | } 30 | 31 | public int compareTo(Task other) { 32 | return Integer.compare(other.priority, this.priority); 33 | } 34 | 35 | public String toString() { 36 | return name + "(" + priority + ")"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/records/Student.java: -------------------------------------------------------------------------------- 1 | package records; 2 | 3 | public record Student(String name, int facultyNumber) { 4 | 5 | public Student { 6 | // this is compact constructor: note the absence of () after Student 7 | if (name.isBlank()) { 8 | throw new IllegalArgumentException("Student's name is blank"); 9 | } 10 | if (facultyNumber < 0) { 11 | throw new IllegalArgumentException("Faculty number is negative"); 12 | } 13 | } 14 | 15 | // Note that we skip explicit fields assignment, i.e. 16 | // this.name = name; 17 | // this.facultyNumber = facultyNumber; 18 | // These assignments are done by the implicit canonical constructor. 19 | // The code in the compact constructor is inserted by the compiler in the beginning of the definition of the canonical one. 20 | 21 | public static void main(String[] args) { 22 | Student student = new Student("Anton Krasimirov", 62805); 23 | System.out.println(student); 24 | Student anotherStudent = new Student(" ", 42365); // throws exception at runtime 25 | System.out.println(anotherStudent); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/heapandstack/HeapAndStackExample.java: -------------------------------------------------------------------------------- 1 | package heapandstack; 2 | 3 | public class HeapAndStackExample { 4 | 5 | public static void heapExample() { 6 | // Creating objects on the heap 7 | Person person1 = new Person("Alice"); 8 | Person person2 = new Person("Bob"); 9 | 10 | // Storing references to objects on the stack 11 | Person[] people = new Person[2]; 12 | people[0] = person1; 13 | people[1] = person2; 14 | 15 | System.out.println(people[0].name()); 16 | System.out.println(people[1].name()); 17 | } 18 | 19 | public static void stackExample() { 20 | int x = 10; // x is stored on the stack 21 | int y = 20; // y is also stored on the stack 22 | 23 | int result = add(x, y); // result is stored on the stack 24 | System.out.println(result); 25 | } 26 | 27 | public static int add(int a, int b) { 28 | return a + b; // The result is stored on the stack 29 | } 30 | 31 | public static void main(String[] args) { 32 | stackExample(); 33 | heapExample(); 34 | } 35 | 36 | } 37 | 38 | record Person(String name) { 39 | } 40 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/file/step/PrintFiles.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.file.step; 2 | 3 | import java.util.Collection; 4 | import bg.sofia.uni.fmi.mjt.file.File; 5 | import bg.sofia.uni.fmi.mjt.pipeline.step.Step; 6 | 7 | /** 8 | * A pipeline step that prints the content of a collection of {@link File} objects 9 | * to the standard output. 10 | *

11 | * This step does not modify the input collection or the files within it. It simply 12 | * iterates over each {@link File} and prints its content. 13 | */ 14 | public class PrintFiles implements Step, Collection> { 15 | 16 | /** 17 | * Prints the content of each {@link File} in the input collection. 18 | * 19 | * @param input the collection of files to print 20 | * @return the same collection of files, unchanged 21 | * 22 | * @throws IllegalArgumentException if the input collection is null 23 | */ 24 | @Override 25 | public Collection process(Collection input) { 26 | for (File f : input) { 27 | System.out.println(f.getContent()); 28 | } 29 | 30 | return input; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/DefaultInterfaceExamples.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.lockable; 2 | 3 | public class DefaultInterfaceExamples { 4 | 5 | public static void main(String... args) { 6 | 7 | Door someDoor = new Door(); 8 | Lockable anotherDoor = new Door(); 9 | Lockable someSafe = new Safe(); 10 | anotherDoor.lock(); // Door locked. 11 | System.out.println(someSafe.isLocked()); // false 12 | System.out.println(someDoor.isLocked()); // true 13 | 14 | Object obj = new Safe(); 15 | 16 | // classic instanceof: explicit cast is needed in the if body 17 | if (obj instanceof Lockable) { 18 | ((Lockable) obj).lock(); // Safe locked. 19 | } 20 | 21 | // New in Java 17: pattern matching for instanceof 22 | if (someDoor instanceof Door d) { 23 | d.lock(); // Door locked. 24 | } 25 | 26 | Lockable door = Lockable.of("door"); 27 | Lockable safe = Lockable.of("safe"); 28 | Lockable vault = Lockable.of("vault"); 29 | 30 | Lockable[] lockables = {door, safe, vault}; 31 | 32 | for (Lockable toLock : lockables) { 33 | toLock.lock(); 34 | } 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /05-generics/snippets/src/BridgeMethods.java: -------------------------------------------------------------------------------- 1 | class Box { 2 | private T value; 3 | 4 | public void setValue(T value) { 5 | this.value = value; 6 | } 7 | } 8 | 9 | class BoxOfInt extends Box { 10 | private Integer value; 11 | 12 | @Override 13 | public void setValue(Integer value) { 14 | this.value = value; 15 | } 16 | 17 | /* 18 | After type parameter erasure, the overriden setValue() method in the superclass and here 19 | would have different signatures: 20 | 21 | public void setValue(Object value) { this.value = value; } // in Box 22 | public void setValue(Integer value) { this.value = value; } // in BoxOfInt 23 | 24 | To solve this, the compiler generates a synthetic method in BoxOfInt, called a "bridge method": 25 | 26 | public void setValue(Object value) { setValue((Integer) value); } // in BoxOfInt 27 | 28 | Bridge methods are not visible in the source code but can be seen in the resulting bytecode. 29 | Have a look disassembling it with javap -c -v BoxOfInt.class 30 | */ 31 | 32 | } 33 | 34 | public class BridgeMethods { 35 | 36 | public static void main(String... args) { 37 | Box boxOfInt = new BoxOfInt(); 38 | boxOfInt.setValue(1); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /09-threads/snippets/src/BankAccount.java: -------------------------------------------------------------------------------- 1 | public class BankAccount { 2 | 3 | // You can test removing explicit synchronization and use AtomicInteger here 4 | private static int opCount = 0; 5 | 6 | // Holder's name 7 | protected String name; 8 | 9 | // Balance 10 | protected double balance = 0; 11 | 12 | public BankAccount(String name, double balance) { 13 | this.name = name; 14 | this.balance = balance; 15 | } 16 | 17 | public BankAccount(String name) { 18 | this.name = name; 19 | } 20 | 21 | public synchronized void deposit(double amount) { 22 | this.balance += amount; 23 | incrementOpCount(); 24 | } 25 | 26 | public synchronized void withdraw(double amount) { 27 | this.balance -= amount; 28 | incrementOpCount(); 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | // is this thread-safe? 36 | public static void incrementOpCount() { 37 | opCount++; 38 | } 39 | 40 | // is this thread-safe? 41 | public static int getOpCount() { 42 | return opCount; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return name + "'s balance is " + balance; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/controversial.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | The Controversial Ruleset contains rules that, for whatever 9 | reason, are considered controversial. This version of the ruleset 10 | includes only some of the controversial rules from the main PMD 11 | rulesets/java/controversial.xml ruleset, and provides alternate messages. 12 | 13 | 14 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/argumentpassing/ReferencesExample.java: -------------------------------------------------------------------------------- 1 | package argumentpassing; 2 | 3 | public class ReferencesExample { 4 | 5 | public static void main(String[] args) { 6 | Person person = new Person("Alice"); 7 | 8 | System.out.println("Before modifyReference: " + person.getName()); 9 | modifyReference(person); 10 | System.out.println("After modifyReference: " + person.getName()); 11 | 12 | System.out.println("Before modifyObject: " + person.getName()); 13 | modifyObject(person); 14 | System.out.println("After modifyObject: " + person.getName()); 15 | } 16 | 17 | public static void modifyObject(Person p) { 18 | p.setName("Bob"); 19 | System.out.println("Inside modifyObject: " + p.getName()); 20 | } 21 | 22 | public static void modifyReference(Person p) { 23 | p = new Person("Mary"); 24 | System.out.println("Inside modifyReference: " + p.getName()); 25 | } 26 | 27 | } 28 | 29 | class Person { 30 | 31 | private String name; 32 | 33 | public Person(String name) { 34 | this.name = name; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/enums/DaysExample.java: -------------------------------------------------------------------------------- 1 | package enums; 2 | 3 | import java.util.Arrays; 4 | 5 | class DaysExample { 6 | 7 | private Day day; 8 | 9 | public DaysExample(Day day) { 10 | this.day = day; 11 | } 12 | 13 | public static void main(String[] args) { 14 | DaysExample example = new DaysExample(Day.TUESDAY); 15 | example.tellItLikeItIs(); // Midweek days are so-so. 16 | 17 | // The values() method is a special method added by the compiler 18 | Day[] days = Day.values(); 19 | System.out.println(Arrays.toString(days)); // [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY] 20 | 21 | // The name must match exactly the identifier used to declare the enum constant in this type. 22 | System.out.println(Day.valueOf("MONDAY")); // MONDAY 23 | 24 | System.out.println(Day.MONDAY.getAbbreviation()); // Mon. 25 | } 26 | 27 | public void tellItLikeItIs() { 28 | String message = switch (day) { 29 | case MONDAY -> "Mondays are bad."; 30 | case FRIDAY -> "Fridays are better."; 31 | case SATURDAY, SUNDAY -> "Weekends are best."; 32 | default -> "Midweek days are so-so."; 33 | }; 34 | 35 | System.out.println(message); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/snippets/src/initializers/InitializersDemo.java: -------------------------------------------------------------------------------- 1 | package initializers; 2 | 3 | class InitializersDemoBase { 4 | private int x; 5 | private static int y; 6 | 7 | { // cannot be static - results in compilation error 8 | this.x = 1; 9 | System.out.println("Parent initializer executed"); 10 | } 11 | 12 | static { 13 | InitializersDemoBase.y = 1; 14 | System.out.println("Parent static initializer executed"); 15 | } 16 | 17 | public InitializersDemoBase() { 18 | System.out.println("Parent constructor executed"); 19 | } 20 | } 21 | 22 | public class InitializersDemo extends InitializersDemoBase { 23 | private int a; 24 | private static int b; 25 | 26 | { 27 | a = 5; 28 | System.out.println("Child initializer 1 executed"); 29 | } 30 | 31 | static { 32 | b = 7; 33 | System.out.println("Child static initializer executed"); 34 | } 35 | 36 | public InitializersDemo() { 37 | a = 10; 38 | b = 10; 39 | System.out.println("Child constructor executed"); 40 | } 41 | 42 | { 43 | a = 16; 44 | System.out.println("Child initializer 2 executed"); 45 | } 46 | 47 | public static void main(String[] args) { 48 | new InitializersDemo(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /05-generics/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/snippets/src/bg/sofia/uni/fmi/mjt/ints/IntsSum.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.ints; 2 | 3 | import org.w3c.dom.ls.LSOutput; 4 | 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | public class IntsSum { 9 | 10 | static void main() { 11 | Set numbers = Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 12 | 13 | int sumOf5 = numbers 14 | .stream() 15 | .sorted() // would this make any difference? 16 | .limit(5) 17 | .mapToInt(Integer::intValue) 18 | .sum(); 19 | 20 | System.out.println(sumOf5); // what will be the result? 21 | 22 | // Map-Reduce: Divide and Conquer for Data 23 | // Map-Reduce is a two-step recipe for processing massive amounts of data: 24 | // 1. Map phase: Break the problem into smaller independent pieces and process each piece in parallel 25 | // 2. Reduce phase: Combine all the results into one final answer 26 | List listOfnumbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 27 | 28 | int result = listOfnumbers.stream() 29 | .map(n -> n * 2) // MAP phase: transform each element 30 | .reduce(0, Integer::sum); // REDUCE phase: combine all results 31 | 32 | System.out.println(result); 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/snippets/src/bg/sofia/uni/fmi/mjt/peaks/model/Peak.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.peaks.model; 2 | 3 | /** 4 | * Record, който съхранява информация за един връх от mountains.txt 5 | * 6 | * @param pos - Позиция по височина - мястото по височина на съответния връх 7 | * @param name - Име (на върха) 8 | * @param height - Височина (в метри) 9 | * @param prominence - Изпъкналост (в метри) - показва височината на върха от най-високата седловина, 10 | * свързваща го с по-висок връх) (виж Topographic prominence) 11 | * @param range - Планина – от коя планинска верига е част върхът 12 | * @param firstAscent - Година на първо изкачване 13 | * @param totalAscents - Брой изкачвания след 2004 г. 14 | */ 15 | public record Peak(int pos, String name, double height, double prominence, String range, int firstAscent, 16 | int totalAscents) { 17 | 18 | private static final String PEAK_ATTRIBUTE_DELIMITER = ","; 19 | 20 | public static Peak of(String line) { 21 | final String[] tokens = line.split(PEAK_ATTRIBUTE_DELIMITER); 22 | return new Peak(Integer.parseInt(tokens[0]), tokens[1], Double.parseDouble(tokens[2]), 23 | Double.parseDouble(tokens[3]), tokens[4], Integer.parseInt(tokens[5]), Integer.parseInt(tokens[6])); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /09-threads/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /10-network/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /01-intro-to-java/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /02-oop-in-java-i/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /03-oop-in-java-ii/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/unusedcode.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | Detects when a private field is declared and/or assigned a value, 9 | but not used. This version of the ruleset includes alternate 10 | messages from the main PMD rulesets/java/unusedcode.xml ruleset. 11 | 12 | 13 | 16 | 19 | 22 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /04-collections-clean-code/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /07-io-streams-and-files/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lecture/slides.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [MJT2026] Modern Java Technologies Lecture 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /07-io-streams-and-files/snippets/src/bg/sofia/uni/fmi/mjt/io/SystemStreamsRedirector.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.io; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.PrintStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | 10 | public class SystemStreamsRedirector { 11 | 12 | static void main() throws IOException { 13 | Path fileOut = Path.of("system-out.txt"); 14 | 15 | Path fileIn = Path.of("system-in.txt"); 16 | 17 | redirectSystemOut(fileOut); 18 | String stringFromSystemIn = readFromSystemIn(); 19 | System.out.println(stringFromSystemIn); 20 | 21 | redirectSystemInFrom(fileIn); 22 | stringFromSystemIn = readFromSystemIn(); 23 | System.out.println(stringFromSystemIn); 24 | } 25 | 26 | public static void redirectSystemOut(Path file) throws IOException { 27 | PrintStream fileStream = new PrintStream(Files.newOutputStream(file)); 28 | System.setOut(fileStream); 29 | } 30 | 31 | public static void redirectSystemInFrom(Path file) throws IOException { 32 | System.setIn(Files.newInputStream(file)); 33 | } 34 | 35 | public static String readFromSystemIn() throws IOException { 36 | var br = new BufferedReader(new InputStreamReader(System.in)); 37 | return br.readLine(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/Project.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.statics; 2 | 3 | public class Project { 4 | 5 | private static final String PROJECT_PREFIX = "proj-"; // constant 6 | private static int totalProjectInstances; 7 | 8 | private String name; 9 | 10 | public Project() { 11 | // We can use a static variable to count the number of Project instances created. 12 | // All instances of Project will share the same copy of the variable. 13 | 14 | name = PROJECT_PREFIX + totalProjectInstances++; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public static int getTotalProjectInstances() { 22 | return totalProjectInstances; 23 | } 24 | 25 | // We cannot use instance variables/methods in static methods because 26 | // static methods are not bound to any instance, but rather to the class itself 27 | // Uncommenting the method below will not compile: 28 | // "non-static variable name cannot be referenced from a static context" 29 | 30 | //public static void printName() { 31 | // System.out.println(name); 32 | //} 33 | 34 | public static void main(String... s) { 35 | System.out.println(new Project().getName()); 36 | System.out.println(new Project().getName()); 37 | System.out.println(new Project().getName()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /10-network/snippets/src/threadpools/VirtualThreadPoolExample.java: -------------------------------------------------------------------------------- 1 | package threadpools; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class VirtualThreadPoolExample { 7 | 8 | static void main() { 9 | 10 | // Create an executor service using a new virtual threads for every new task 11 | ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor(); 12 | 13 | try (executorService) { 14 | 15 | // Submit several tasks to the executor 16 | for (int i = 0; i < 10; i++) { 17 | 18 | final int taskId = i; 19 | 20 | executorService.submit(() -> { 21 | // Note that virtual threads are created without a name by default to minimize overhead 22 | // and because the high number of threads typically makes naming them impractical. 23 | System.out.println("Running task " + taskId + " in " + Thread.currentThread()); 24 | 25 | // Simulate some work with sleep 26 | try { 27 | Thread.sleep(1_000); 28 | } catch (InterruptedException e) { 29 | e.printStackTrace(); 30 | } 31 | }); 32 | } 33 | 34 | } // executorService will be autoclosed --> auto shut down 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /07-io-streams-and-files/snippets/src/bg/sofia/uni/fmi/mjt/io/WritingToAndReadingFromFile.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.io; 2 | 3 | import java.io.IOException; 4 | import java.io.UncheckedIOException; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | 8 | public class WritingToAndReadingFromFile { 9 | 10 | static void main() { 11 | Path filePath = Path.of("writingAndReadingFromFile.txt"); 12 | String text = "Write this string to my file" + System.lineSeparator(); 13 | 14 | writeToFile(filePath, text); 15 | readFromFile(filePath); 16 | } 17 | 18 | private static void writeToFile(Path filePath, String text) { 19 | try (var bufferedWriter = Files.newBufferedWriter(filePath)) { 20 | bufferedWriter.write(text); 21 | bufferedWriter.flush(); 22 | } catch (IOException e) { 23 | throw new UncheckedIOException("A problem occurred while writing to a file", e); 24 | } 25 | } 26 | 27 | private static void readFromFile(Path filePath) { 28 | try (var bufferedReader = Files.newBufferedReader(filePath)) { 29 | String line; 30 | 31 | while ((line = bufferedReader.readLine()) != null) { 32 | System.out.println(line); 33 | } 34 | } catch (IOException e) { 35 | throw new UncheckedIOException("A problem occurred while reading from a file", e); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /10-network/snippets/src/threadsafecollections/BlockingQueueExample.java: -------------------------------------------------------------------------------- 1 | package threadsafecollections; 2 | 3 | import java.util.concurrent.ArrayBlockingQueue; 4 | import java.util.concurrent.BlockingQueue; 5 | 6 | public class BlockingQueueExample { 7 | 8 | public static void main(String[] args) { 9 | BlockingQueue queue = new ArrayBlockingQueue<>(5); 10 | 11 | // Producer Thread 12 | Thread producer = new Thread(() -> { 13 | try { 14 | for (int i = 0; i < 10; i++) { 15 | Thread.sleep(500); 16 | queue.put(i); // Blocks if the queue is full 17 | System.out.println("Produced: " + i); 18 | } 19 | } catch (InterruptedException e) { 20 | Thread.currentThread().interrupt(); 21 | } 22 | }); 23 | 24 | // Consumer Thread 25 | Thread consumer = new Thread(() -> { 26 | try { 27 | for (int i = 0; i < 10; i++) { 28 | Thread.sleep(1_500); 29 | Integer value = queue.take(); // Blocks if the queue is empty 30 | System.out.println("Consumed: " + value); 31 | } 32 | } catch (InterruptedException e) { 33 | Thread.currentThread().interrupt(); 34 | } 35 | }); 36 | 37 | producer.start(); 38 | consumer.start(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /09-threads/snippets/src/howmany/HowManyThreadsHelper.java: -------------------------------------------------------------------------------- 1 | package howmany; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | public class HowManyThreadsHelper { 6 | 7 | private static final long SLEEP_MILLIS = 100; 8 | 9 | static void doSomething() { 10 | long millis = 0; 11 | while (!Thread.currentThread().isInterrupted()) { 12 | try { 13 | Thread.sleep(SLEEP_MILLIS); 14 | millis += SLEEP_MILLIS; 15 | } catch (InterruptedException e) { 16 | Thread.currentThread().interrupt(); 17 | } 18 | } 19 | System.out.println("I died after " + millis + " milliseconds"); 20 | } 21 | 22 | static void waitForVirtualThreadsToCatchUp( 23 | int startedThreads, AtomicLong runningThreadsCounter, long startTime) 24 | throws InterruptedException { 25 | long runningThreads; 26 | while (startedThreads > (runningThreads = runningThreadsCounter.get())) { 27 | long time = System.currentTimeMillis() - startTime; 28 | System.out.printf( 29 | "Waiting for virtual threads to catch up: (%,d running after %,d ms)...%n", 30 | runningThreads, time); 31 | Thread.sleep(100); 32 | } 33 | long time = System.currentTimeMillis() - startTime; 34 | System.out.printf( 35 | "Virtual threads caught up: %,d running after %,d ms%n", runningThreads, time); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /10-network/snippets/src/network/NetworkInterfacesLister.java: -------------------------------------------------------------------------------- 1 | void main() throws Exception { 2 | 3 | Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); 4 | 5 | while (interfaces.hasMoreElements()) { 6 | NetworkInterface nic = interfaces.nextElement(); 7 | 8 | IO.println("----------------------------------------------------"); 9 | IO.println("Name : " + nic.getName()); 10 | IO.println("Up : " + nic.isUp()); 11 | IO.println("Loopback : " + nic.isLoopback()); 12 | IO.println("Virtual : " + nic.isVirtual()); 13 | IO.println("PointToPoint : " + nic.isPointToPoint()); 14 | IO.println("MTU : " + nic.getMTU()); 15 | 16 | byte[] mac = nic.getHardwareAddress(); 17 | IO.print("MAC Address : "); 18 | if (mac != null) { 19 | for (int i = 0; i < mac.length; i++) { 20 | System.out.printf("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""); 21 | } 22 | IO.println(); 23 | } else { 24 | IO.println("N/A"); 25 | } 26 | 27 | // List all IPv4/IPv6 addresses 28 | IO.println("IP Addresses :"); 29 | Enumeration addrs = nic.getInetAddresses(); 30 | while (addrs.hasMoreElements()) { 31 | InetAddress addr = addrs.nextElement(); 32 | IO.println(" - " + addr.getHostAddress()); 33 | } 34 | IO.println(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/file/step/SplitFile.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.file.step; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | import bg.sofia.uni.fmi.mjt.file.File; 6 | import bg.sofia.uni.fmi.mjt.pipeline.step.Step; 7 | 8 | /** 9 | * A pipeline step that splits the content of a {@link File} into multiple 10 | * smaller {@link File} objects, one for each word (split by whitespace). 11 | *

12 | * The resulting {@link File} objects are stored in a {@link Set}. To avoid 13 | * duplicates 14 | */ 15 | public class SplitFile implements Step> { 16 | 17 | private static final String whitespace_regex = "\\s+"; 18 | 19 | /** 20 | * Splits the content of the input {@link File} by whitespace and returns 21 | * a {@link Set} of new {@link File} objects, each containing one part. 22 | * 23 | * @param input the file whose content will be split 24 | * @return a set of new {@link File} objects containing the split content. 25 | * No files with duplicate content are included in the set. 26 | * 27 | * @throws IllegalArgumentException if the input file or its content is null 28 | */ 29 | @Override 30 | public Set process(File input) { 31 | Set result = new HashSet<>(); 32 | String[] parts = input.getContent().split(whitespace_regex); 33 | 34 | for (String part : parts) { 35 | result.add(new File(part)); 36 | } 37 | 38 | return result; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /07-io-streams-and-files/snippets/src/bg/sofia/uni/fmi/mjt/io/DiskSizeEstimator.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.io; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.FileStore; 5 | import java.nio.file.FileSystems; 6 | import java.util.Locale; 7 | 8 | public class DiskSizeEstimator { 9 | 10 | private static final double KILOBYTE = 1024.0; 11 | 12 | static void main() throws IOException { 13 | 14 | // обхождаме всички дялове на файловата система по подразбиране 15 | Iterable partitions = FileSystems.getDefault().getFileStores(); 16 | 17 | for (FileStore fs : partitions) { 18 | long totalSpace = fs.getTotalSpace(); 19 | long unallocatedSpace = fs.getUnallocatedSpace(); 20 | long usableSpace = fs.getUsableSpace(); 21 | 22 | System.out.println("Partition: " + fs.name()); 23 | System.out.println( 24 | String.format(Locale.US, "Total space: %,d bytes (%.2f GB)", totalSpace, toGigabytes(totalSpace))); 25 | System.out.println(String.format(Locale.US, "Unallocated space: %,d bytes (%.2f GB)", unallocatedSpace, 26 | toGigabytes(unallocatedSpace))); 27 | System.out.println( 28 | String.format(Locale.US, "Usable space: %,d bytes (%.2f GB)", usableSpace, toGigabytes(usableSpace))); 29 | System.out.println(); 30 | } 31 | 32 | } 33 | 34 | private static double toGigabytes(long bytes) { 35 | return bytes / (KILOBYTE * KILOBYTE * KILOBYTE); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/braces.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | The Braces Ruleset contains a collection of braces rules. This 9 | version of the ruleset includes alternate messages from the main 10 | PMD rulesets/java/braces.xml ruleset. 11 | 12 | 13 | 17 | 18 | 22 | 23 | 27 | 28 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /09-threads/snippets/src/howmany/HowManyPlatformThreadsDoingSomething.java: -------------------------------------------------------------------------------- 1 | package howmany; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | import static howmany.HowManyThreadsHelper.doSomething; 6 | 7 | public class HowManyPlatformThreadsDoingSomething { 8 | 9 | // ATTENTION: THIS MAY CRASH YOUR MACHINE! 10 | 11 | // Enable NMT and inspect native vs heap memory: start JVM with -XX:NativeMemoryTracking=summary, 12 | // use `jcmd VM.native_memory` for native breakdown (e.g., per-thread stacks), 13 | // and `jmap -histo ` for on-heap class sizes—useful when many platform threads cause OOM 14 | // due to native (not heap) usage. 15 | 16 | // Safe limit on Windows 11 with 64 GB: 20,000 17 | private static final int NUMBER_OF_THREADS = 20_000; 18 | 19 | static void main() throws InterruptedException { 20 | AtomicLong runningThreadsCounter = new AtomicLong(); 21 | 22 | long startTime = System.currentTimeMillis(); 23 | 24 | for (int i = 1; i <= NUMBER_OF_THREADS; i++) { 25 | Thread.ofPlatform() 26 | .start( 27 | () -> { 28 | runningThreadsCounter.incrementAndGet(); 29 | doSomething(); 30 | }); 31 | 32 | if (i % 1_000 == 0) { 33 | long time = System.currentTimeMillis() - startTime; 34 | System.out.printf( 35 | "%,d threads started, %,d threads running after %,d ms%n", 36 | i, runningThreadsCounter.get(), time); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /playground/01-stock-exchange/README.md: -------------------------------------------------------------------------------- 1 | ### Стокова борса :currency_exchange: 2 | 3 | ### Условие 4 | 5 | Кой е подходящият момент да купим и продадем акции, така че да си максимизираме печалбата? 6 | 7 | Създайте публичен клас `StockExchange` с метод 8 | 9 | ```java 10 | public static int maxProfit(int[] prices) 11 | ``` 12 | 13 | който определя максималната печалба от покупко-продажбата на акции на борсата. Методът приема като параметър масив от цели числа, които представят предсказания за цената на акциите на дадена компания в поредни дни в бъдещето: `i`-тият елемент на масива представлява цената на акциите в `i`-тият ден след днешния. В дадения времеви интервал могат да се завършат най-много две транзакции. Не може да се случват множество паралелни транзакции (т.е. трябва да продадете акции преди да може да купите отново). 14 | 15 | ### Примери 16 | 17 | | Вход | Резултат | Обяснение | 18 | | :----------------------------------- |:---------| :--------- | 19 | | {7, 1, 5, 3, 6, 4} | 7 | Купваме в ден 2 (цена = 1) и продаваме в ден 3 (цена = 5), печалба = 5-1 = 4.
После купуваме в ден 4 (цена = 3) и продаваме в ден 5 (цена = 6), печалба = 6 - 3 = 3. | 20 | | {1, 2, 3, 4, 5} | 4 | Купваме в ден 1 (цена = 1) и продаваме в ден 5 (цена = 5), печалба = 5-1 = 4.
Забележете, че не може да купим в ден 1, да купим в ден 2 и да ги продадем по-късно,
защото би означавало да правим няколко паралелни тракзакции, засичащи се във времето.
Трябва да продадем акции преди да може да купим отново. | 21 | | {7, 6, 4, 3, 1} | 0 | В този случай, нямаме полезен ход, максималната печалба е 0 (ако не търгуваме). | 22 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/comparators/Car.java: -------------------------------------------------------------------------------- 1 | package comparators; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Represents a simple car with basic attributes. 7 | * Implements Comparable to allow natural ordering by top speed (ascending). 8 | */ 9 | public class Car implements Comparable { 10 | private final String vin; 11 | private final int topSpeed; 12 | private final String color; 13 | private final String brand; 14 | 15 | public Car(String vin, int topSpeed, String color, String brand) { 16 | this.vin = vin; 17 | this.topSpeed = topSpeed; 18 | this.color = color; 19 | this.brand = brand; 20 | } 21 | 22 | public String getVin() { 23 | return vin; 24 | } 25 | 26 | public int getTopSpeed() { 27 | return topSpeed; 28 | } 29 | 30 | public String getColor() { 31 | return color; 32 | } 33 | 34 | public String getBrand() { 35 | return brand; 36 | } 37 | 38 | @Override 39 | public int compareTo(Car other) { 40 | return Integer.compare(this.topSpeed, other.topSpeed); 41 | } 42 | 43 | @Override 44 | public boolean equals(Object o) { 45 | if (this == o) return true; 46 | if (!(o instanceof Car)) return false; 47 | Car car = (Car) o; 48 | return Objects.equals(vin, car.vin); 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | return Objects.hash(vin); 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return String.format("%s(%s, %dkm/h, %s)", brand, color, topSpeed, vin); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /09-threads/snippets/src/AtomicIntegerExample.java: -------------------------------------------------------------------------------- 1 | import java.util.concurrent.atomic.AtomicInteger; 2 | 3 | public class AtomicIntegerExample { 4 | 5 | public static void main(String args[]) throws InterruptedException { 6 | AtomicInteger atomicInt = new AtomicInteger(); 7 | NonAtomicInteger nonAtomicInt = new NonAtomicInteger(); 8 | 9 | Runnable r = () -> { 10 | for (int j = 0; j < 100_000; j++) { 11 | atomicInt.getAndIncrement(); 12 | nonAtomicInt.getAndIncrement(); 13 | } 14 | System.out.println("Сбогом, жесток свят " + Thread.currentThread().getName()); 15 | }; 16 | 17 | Thread t1 = new Thread(r); 18 | Thread t2 = new Thread(r); 19 | Thread t3 = new Thread(r); 20 | Thread t4 = new Thread(r); 21 | 22 | t1.start(); 23 | t2.start(); 24 | t3.start(); 25 | t4.start(); 26 | 27 | t1.join(); 28 | t2.join(); 29 | t3.join(); 30 | t4.join(); 31 | 32 | System.out.printf("The atomic integer should be 400000, it is %d%n", atomicInt.get()); 33 | System.out.printf("The non-atomic integer should be 400000, it is %d%n", nonAtomicInt.get()); 34 | } 35 | 36 | public static class NonAtomicInteger { 37 | private int i; 38 | 39 | public NonAtomicInteger() { 40 | i = 0; 41 | } 42 | 43 | public int getAndIncrement() { 44 | return i++; 45 | } 46 | 47 | public int get() { 48 | return i; 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/MethodHidingExample.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.statics; 2 | 3 | class Parent { 4 | void display() { 5 | System.out.println("Non-static method in Parent"); 6 | } 7 | 8 | static void staticDisplay() { 9 | System.out.println("Static method in Parent"); 10 | } 11 | } 12 | 13 | class Child extends Parent { 14 | @Override 15 | void display() { 16 | System.out.println("Non-static method in Child"); 17 | } 18 | 19 | static void staticDisplay() { 20 | System.out.println("Static method in Child (Hidden)"); 21 | } 22 | } 23 | 24 | public class MethodHidingExample { 25 | public static void main(String[] args) { 26 | Parent parent = new Parent(); 27 | Parent childAsParent = new Child(); 28 | Child child = new Child(); 29 | 30 | parent.display(); // Output: Non-static method in Parent 31 | childAsParent.display(); // Output: Non-static method in Child 32 | 33 | parent.staticDisplay(); // Output: Static method in Parent; same as calling Parent.staticDisplay(); 34 | childAsParent.staticDisplay(); // Output: Static method in Parent, because the reference type is Parent; same as calling Parent.staticDisplay(); 35 | child.staticDisplay(); // Output: Static method in Child (Hidden), because the reference type is Child;same as calling Child.staticDisplay(); 36 | 37 | // In summary - static methods belong to the class and no overriding is possible - 38 | // it's possible to redefine the same method in the child class, but that's not overriding. 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /05-generics/snippets/src/Pair.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | import java.util.Set; 3 | 4 | public class Pair { 5 | 6 | private K key; 7 | private V value; 8 | 9 | public Pair(K key, V value) { 10 | this.key = key; 11 | this.value = value; 12 | } 13 | 14 | public K getKey() { 15 | return key; 16 | } 17 | 18 | public void setKey(K key) { 19 | this.key = key; 20 | } 21 | 22 | public V getValue() { 23 | return value; 24 | } 25 | 26 | public void setValue(V value) { 27 | this.value = value; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "Pair{" + 33 | "key=" + key + 34 | ", value=" + value + 35 | '}'; 36 | } 37 | 38 | public static void main(String[] args) { 39 | Pair pair1 = new Pair<>("Stoyo", 1); 40 | Pair pair2 = new Pair<>("Boyo", 6); 41 | 42 | Pair pair3 = new Pair<>(1.0, 1.0); 43 | 44 | System.out.println(Util.areEqual(pair1, pair2)); 45 | // the next line will not compile: "reason: Incompatible equality constraint: Double and String" 46 | //System.out.println(Util.areEqual(pair1, pair3)); 47 | 48 | Pair, Set> pair4 = new Pair<>(List.of("FMI", "rulez"), Set.of(2024, 2025)); 49 | } 50 | 51 | } 52 | 53 | class Util { 54 | // Generic static method 55 | public static boolean areEqual(Pair p1, Pair p2) { 56 | return p1.getKey().equals(p2.getKey()) && 57 | p1.getValue().equals(p2.getValue()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/snippets/src/bg/sofia/uni/fmi/mjt/MethRefExample.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt; 2 | 3 | import java.util.function.Function; 4 | import java.util.function.IntConsumer; 5 | import java.util.function.Supplier; 6 | 7 | public class MethRefExample { 8 | 9 | public MethRefExample() { 10 | System.out.println("No arg constructor invoked"); 11 | } 12 | 13 | public MethRefExample(String s) { 14 | System.out.println("String arg constructor invoked with param " + s); 15 | } 16 | 17 | public static void fun() { 18 | System.out.println("fun() invoked"); 19 | } 20 | 21 | public static void fun(int i) { 22 | System.out.println("fun(int) invoked with argument " + i); 23 | } 24 | 25 | static void main() { 26 | 27 | // method reference to overloaded constructor 28 | Function stringConstructorRef1 = MethRefExample::new; 29 | Function stringConstructorRef2 = s -> new MethRefExample(s); 30 | MethRefExample example1 = stringConstructorRef1.apply("FMI"); 31 | MethRefExample example2 = stringConstructorRef1.apply("Rulez"); 32 | 33 | Supplier defaultConstructorRef = MethRefExample::new; 34 | MethRefExample example3 = defaultConstructorRef.get(); 35 | 36 | // method reference to overloaded methods 37 | IntConsumer methRef1 = MethRefExample::fun; 38 | methRef1.accept(5); 39 | 40 | NoArgNoReturn methRef2 = MethRefExample::fun; 41 | methRef2.accept(); 42 | 43 | } 44 | 45 | @FunctionalInterface 46 | interface NoArgNoReturn { 47 | void accept(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/imports.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | These rules deal with different problems that can occur with a 9 | class' import statements. This version of the ruleset includes 10 | alternate messages from the main PMD rulesets/java/imports.xml ruleset. 11 | 12 | 13 | 17 | 18 | 22 | 23 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/snippets/src/bg/sofia/uni/fmi/mjt/employees/EmployeesExample.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.employees; 2 | 3 | import java.util.List; 4 | 5 | public class EmployeesExample { 6 | 7 | static void main() { 8 | Employee e1 = new Employee(1, "Бай Кольо", 56, 1200.00, 340.00); 9 | Employee e2 = new Employee(2, "Шефа", 43, 15000.00, 30000.00); 10 | Employee e3 = new Employee(3, "Стажанта", 20, 850.00, 0.00); 11 | 12 | List employees = List.of(e1, e2, e3); 13 | 14 | System.out.println(getEmployeeSalariesTotal(employees)); 15 | } 16 | 17 | public static double getEmployeeSalariesTotal(List employees) { 18 | // Stream -> reduce -> V 19 | // 20 | // initial value (identity): the initial value of the reduction and the default result if the stream is empty 21 | // accumulator: This is a BinaryOperator function that takes two parameters: 22 | // a partial result of the reduction operation and the next element of the stream 23 | // combiner: combine the results of the accumulator function when processing elements in parallel 24 | // The combiner is necessary in parallel operations, where the input stream is divided into 25 | // multiple sub-streams that are processed independently and then the partial results 26 | // are combined into a final result. 27 | return employees.parallelStream() 28 | .reduce( 29 | 0.0, // initial value 30 | (res, el) -> res + el.salary(), // accumulator 31 | (left, right) -> left + right); // combiner 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /09-threads/snippets/src/SimpleDeadLock.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Trivial deadlock example. 3 | * The two threads take locks in exchanged order. 4 | */ 5 | public class SimpleDeadLock { 6 | 7 | static void main() { 8 | // Two shared resources 9 | Object vinegar = new Object(); 10 | Object oil = new Object(); 11 | 12 | // Friend1 always gets oil first then vinegar 13 | Thread friend1 = new Thread(new Runnable() { 14 | @Override 15 | public void run() { 16 | synchronized (oil) { 17 | try { 18 | Thread.sleep(500); 19 | } catch (InterruptedException e) { 20 | e.printStackTrace(); 21 | } 22 | 23 | synchronized (vinegar) { 24 | System.out.println("Friend1 made his salad"); 25 | } 26 | } 27 | } 28 | }); 29 | 30 | // Friend2 always gets vinegar first then oil 31 | Thread friend2 = new Thread(new Runnable() { 32 | @Override 33 | public void run() { 34 | // To resolve the deadlock 35 | // lock the monitors in the same order 36 | synchronized (vinegar) { 37 | try { 38 | Thread.sleep(500); 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | 43 | synchronized (oil) { 44 | System.out.println("Friend2 made his salad"); 45 | } 46 | } 47 | } 48 | }); 49 | 50 | friend1.start(); 51 | friend2.start(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /09-threads/snippets/src/howmany/HowManyPlatformThreads.java: -------------------------------------------------------------------------------- 1 | package howmany; 2 | 3 | import java.time.Duration; 4 | import java.util.concurrent.atomic.AtomicLong; 5 | 6 | public class HowManyPlatformThreads { 7 | 8 | // ATTENTION: THIS MAY CRASH YOUR MACHINE! 9 | 10 | // Enable NMT and inspect native vs heap memory: start JVM with -XX:NativeMemoryTracking=summary, 11 | // use `jcmd VM.native_memory` for native breakdown (e.g., per-thread stacks), 12 | // and `jmap -histo ` for on-heap class sizes—useful when many platform threads cause OOM 13 | // due to native (not heap) usage. 14 | 15 | // Safe limit on Windows 11 with 64 GB: 20,000 16 | private static final int NUMBER_OF_THREADS = 20_000; 17 | 18 | static void main() throws InterruptedException { 19 | AtomicLong runningThreadsCounter = new AtomicLong(); 20 | 21 | long startTime = System.currentTimeMillis(); 22 | 23 | for (int i = 1; i <= NUMBER_OF_THREADS; i++) { 24 | Thread.ofPlatform() 25 | .start( 26 | () -> { 27 | runningThreadsCounter.incrementAndGet(); 28 | try { 29 | Thread.sleep(Duration.ofDays(100)); 30 | } catch (InterruptedException e) { 31 | // Let the thread die 32 | } 33 | System.out.println("I died"); 34 | }); 35 | 36 | if (i % 1000 == 0) { 37 | long time = System.currentTimeMillis() - startTime; 38 | System.out.printf( 39 | "%,d threads started, %,d threads running after %,d ms%n", 40 | i, runningThreadsCounter.get(), time); 41 | } 42 | 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/instanceoff/InstanceOfExample.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.instanceoff; 2 | 3 | class Shape { 4 | void draw() { 5 | System.out.println("Drawing a shape"); 6 | } 7 | } 8 | 9 | class Circle extends Shape { 10 | @Override 11 | void draw() { 12 | System.out.println("Drawing a circle"); 13 | } 14 | } 15 | 16 | class Rectangle extends Shape { 17 | @Override 18 | void draw() { 19 | System.out.println("Drawing a rectangle"); 20 | } 21 | } 22 | 23 | public class InstanceOfExample { 24 | 25 | public static void main(String[] args) { 26 | Shape[] shapes = new Shape[] { 27 | new Circle(), 28 | new Rectangle(), 29 | new Circle(), 30 | new Rectangle(), 31 | }; 32 | 33 | // old-school way: 34 | for (Shape shape : shapes) { 35 | if (shape instanceof Circle) { 36 | System.out.println("Circle detected:"); 37 | Circle circle = (Circle) shape; // Cast to Circle 38 | circle.draw(); 39 | } else if (shape instanceof Rectangle) { 40 | System.out.println("Rectangle detected:"); 41 | Rectangle rectangle = (Rectangle) shape; // Cast to Rectangle 42 | rectangle.draw(); 43 | } else { 44 | System.out.println("Unknown shape detected."); 45 | shape.draw(); 46 | } 47 | } 48 | 49 | // equivalent with enhanced switch 50 | for (Shape shape : shapes) { 51 | switch (shape) { 52 | case Circle c -> c.draw(); 53 | case Rectangle r -> r.draw(); 54 | default -> System.out.println("Unexpected value: " + shape); 55 | } 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /07-io-streams-and-files/snippets/src/bg/sofia/uni/fmi/mjt/io/DataStreamExample.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.io; 2 | 3 | import java.io.DataInputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.FileInputStream; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.UncheckedIOException; 9 | 10 | public class DataStreamExample { 11 | 12 | static void main() { 13 | writeWithDataStream(); 14 | readDataStream(); 15 | } 16 | 17 | /** 18 | * Writes structured data using DataOutputStream 19 | * https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/io/DataOutputStream.html 20 | */ 21 | private static void writeWithDataStream() { 22 | try (var dataOutputStream = new DataOutputStream(new FileOutputStream("test.dat"))) { 23 | dataOutputStream.writeInt(16); 24 | dataOutputStream.writeFloat(5.2f); 25 | dataOutputStream.writeUTF("Koko"); 26 | dataOutputStream.flush(); 27 | } catch (IOException e) { 28 | throw new UncheckedIOException("A problem occurred while writing to a file", e); 29 | } 30 | } 31 | 32 | /** 33 | * Reads structured data using DataInputStream 34 | * https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/io/DataInputStream.html 35 | */ 36 | private static void readDataStream() { 37 | try (var dataInputStream = new DataInputStream(new FileInputStream("test.dat"))) { 38 | System.out.println("int: " + dataInputStream.readInt()); 39 | System.out.println("float: " + dataInputStream.readFloat()); 40 | System.out.println("string: " + dataInputStream.readUTF()); 41 | } catch (IOException e) { 42 | throw new UncheckedIOException("A problem occurred while reading from a file", e); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /01-intro-to-java/lab/01-unique-substring-finder/README.md: -------------------------------------------------------------------------------- 1 | ## Най-дълга неповтаряща се последователност 🔥 2 | 3 | ### Условие 4 | 5 | Имаш низ от символи (само **малки латински букви**, за да не се набъркваме отсега с Unicode) и искаш да намериш най-дългата непрекъсната поредица, в която няма повтарящи се символи. 6 | Задачата е класическа: полезна е за всичко — от анализ на текстове и логове до оптимизация на памет и компресия на данни. 7 | 8 | Създай публичен клас `UniqueSubstringFinder` с метод 9 | 10 | ```java 11 | public static String longestUniqueSubstring(String s) 12 | ``` 13 | 14 | който приема низ s и връща най-дългия подниз без повторения. 15 | 16 | 🎯 Съвет: Не ти трябват fancy структури от данни, достатъчно е да ползваш масиви и малко логика от първата лекция. 17 | 18 | ### Примери 19 | 20 | 21 | 22 | | Извикване | Резултат | 23 | | :----------------------------------- | :----------- | 24 | | `longestUniqueSubstring("abcabcbb")` | `"abc"` | 25 | | `longestUniqueSubstring("bbbbb")` | `"b"` | 26 | | `longestUniqueSubstring("pwwkew")` | `"wke"` | 27 | | `longestUniqueSubstring("abcdefg")` | `"abcdefg"` | 28 | | `longestUniqueSubstring("x")` | `"x"` | 29 | | `longestUniqueSubstring("")` | `""` | 30 | 31 | 32 | 33 | 👉 За допълнителен контекст и мотивация: 34 | 35 | Освен че се падна на входния тест за MJT2026, задачата често се среща на интервюта (Google, Meta, Amazon), в курсове по алгоритми (MIT, Stanford, Princeton) и на състезания като Codeforces, ICPC и Google Kickstart. 36 | 37 | ### :warning: Забележки 38 | 39 | - Помисли каква е сложността на алгоритъма и дали може да я оптимизираш 40 | - Използването на структури от данни, различни от масив, както и на компаратори, ламбда изрази и прочее **не е позволено** - задачата може и трябва да се реши с помощта на знанията от първата лекция от курса. 41 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/test/bg/sofia/uni/fmi/mjt/OrderedTest.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt; 2 | 3 | import org.junit.jupiter.api.AfterAll; 4 | import org.junit.jupiter.api.AfterEach; 5 | import org.junit.jupiter.api.BeforeAll; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Disabled; 8 | import org.junit.jupiter.api.MethodOrderer; 9 | import org.junit.jupiter.api.Order; 10 | import org.junit.jupiter.api.Test; 11 | import org.junit.jupiter.api.TestMethodOrder; 12 | 13 | import static java.time.Duration.ofMillis; 14 | import static org.junit.jupiter.api.Assertions.assertTimeout; 15 | 16 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 17 | class OrderedTest { 18 | 19 | @BeforeAll 20 | static void setUpTestCase() { 21 | System.out.println("BeforeAll called"); 22 | } 23 | 24 | @AfterAll 25 | static void tearDownTestCase() { 26 | System.out.println("AfterAll called"); 27 | } 28 | 29 | @BeforeEach 30 | void setUp() { 31 | System.out.println("BeforeEach called"); 32 | } 33 | 34 | @AfterEach 35 | void tearDown() { 36 | System.out.println("AfterEach called"); 37 | } 38 | 39 | @Test 40 | @Order(3) 41 | //@Disabled 42 | void testNullValues() { 43 | System.out.println("Test null values"); 44 | } // will execute third 45 | 46 | @Test 47 | @Order(1) 48 | void testEmptyValues() { 49 | System.out.println("Test empty values"); 50 | } // will execute first 51 | 52 | @Test 53 | @Order(2) 54 | void testValidValues() { 55 | System.out.println("Test valid values"); 56 | } // will execute second 57 | 58 | @Test 59 | void testDepositPerformance() { 60 | System.out.println("Test performance"); 61 | 62 | assertTimeout(ofMillis(200), () -> Thread.sleep(120), //wallet.deposit(1250.0), 63 | "Deposit amount too slow"); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | These rules deal with different problems that can occur with 9 | manipulation of the class String or StringBuffer. This version of 10 | the ruleset includes alternate messages from the main PMD 11 | rulesets/java/strings.xml ruleset. 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 | 25 | 26 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /08-lambdas-and-stream-api/snippets/src/bg/sofia/uni/fmi/mjt/gatherers/GatherersExample.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.gatherers; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.stream.Gatherer; 6 | import java.util.stream.Gatherers; 7 | import java.util.stream.Stream; 8 | 9 | public class GatherersExample { 10 | 11 | // Stream Gatherers was a preview feature in Java 22 & 23 12 | // The feature was finalized in Java 24. 13 | // They allow creating custom intermediate operations 14 | 15 | static void main() { 16 | 17 | // Fold example: factorial 18 | // Similar to the terminal "reduce" but returns a stream of its single-element result 19 | Stream.of(1, 2, 3, 4, 5) // ⟵ Source 20 | .gather(Gatherers.fold(() -> 1, (a, b) -> a * b)) // ⟵ Intermediate operation 21 | .forEach(System.out::println); // ⟵ Terminal operation 22 | 23 | var words = List.of("the", "be", "two", "of", "and", "a", "in", "that"); 24 | System.out.println(words); 25 | 26 | // Fixed window example 27 | var wordGroupsFixed = words.stream() // ⟵ Source 28 | .gather(Gatherers.windowFixed(3)) // ⟵ Intermediate operation 29 | .toList(); // ⟵ Terminal operation 30 | System.out.println(wordGroupsFixed); 31 | 32 | // Sliding window example 33 | var wordGroupsSliding = words.stream() // ⟵ Source 34 | .gather(Gatherers.windowSliding(3)) // ⟵ Intermediate operation 35 | .toList(); // ⟵ Terminal operation 36 | System.out.println(wordGroupsSliding); 37 | 38 | // Map concurrent example: leveraging virtual threads 39 | Stream.of(1, 2, 3, 4, 5) 40 | .gather(Gatherers.mapConcurrent(4, a -> a * 2)) 41 | .forEach(System.out::println); 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/collections/products/RecentlyViewedProducts.java: -------------------------------------------------------------------------------- 1 | package collections.products; 2 | 3 | import java.util.LinkedHashSet; 4 | import java.util.Iterator; 5 | 6 | public class RecentlyViewedProducts { 7 | private final int maxSize; 8 | private final LinkedHashSet productIds; 9 | 10 | public RecentlyViewedProducts(int maxSize) { 11 | this.maxSize = maxSize; 12 | this.productIds = new LinkedHashSet<>(); 13 | } 14 | 15 | public void viewProduct(String productId) { 16 | // Remove if already present to update position 17 | productIds.remove(productId); 18 | productIds.add(productId); 19 | 20 | // If size exceeds max, remove oldest 21 | if (productIds.size() > maxSize) { 22 | Iterator it = productIds.iterator(); 23 | it.next(); 24 | it.remove(); 25 | } 26 | } 27 | 28 | public Iterable getRecentlyViewed() { 29 | // Returns products from oldest to newest 30 | return productIds; 31 | } 32 | 33 | public static void main(String... args) { 34 | RecentlyViewedProducts recent = new RecentlyViewedProducts(3); 35 | 36 | recent.viewProduct("P1"); // User views product P1 37 | recent.viewProduct("P2"); // User views product P2 38 | recent.viewProduct("P3"); // User views product P3 39 | System.out.println("After viewing P1, P2, P3: " + recent.getRecentlyViewed()); 40 | 41 | recent.viewProduct("P2"); // User views P2 again (should move to most recent) 42 | System.out.println("After viewing P2 again: " + recent.getRecentlyViewed()); 43 | 44 | recent.viewProduct("P4"); // User views P4 (oldest, P1, should be dropped) 45 | System.out.println("After viewing P4: " + recent.getRecentlyViewed()); 46 | 47 | recent.viewProduct("P3"); // User views P3 again (should move to most recent) 48 | System.out.println("After viewing P3 again: " + recent.getRecentlyViewed()); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /10-network/snippets/src/structuredconcurrency/StructuredConcurrencyDemo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Structured Concurrency Example in Java 25 3 | * 4 | * This example demonstrates Java's StructuredTaskScope, a preview feature in Java 25. 5 | * Structured concurrency allows you to fork multiple tasks within a scope, wait for all 6 | * of them to complete, and handle exceptions in a structured way. 7 | * 8 | * Key points: 9 | * 1. Tasks are forked concurrently using scope.fork(). 10 | * 2. scope.join() waits for all tasks to finish and throws FailedException if any task fails. 11 | * 3. Results are retrieved using subtask.get() after join(). 12 | * 4. Any running tasks are automatically cancelled if one fails. 13 | * 14 | * This makes concurrent code easier to read, safer, and less error-prone than manual thread management. 15 | */ 16 | 17 | void main() { 18 | // Open a structured task scope 19 | try (var scope = StructuredTaskScope.open()) { 20 | 21 | // Fork tasks concurrently 22 | var task1 = scope.fork(() -> work("Task 1", 1000)); 23 | var task2 = scope.fork(() -> work("Task 2 (fails)", 500)); 24 | var task3 = scope.fork(() -> work("Task 3", 800)); 25 | 26 | // Wait for all tasks to complete; throws FailedException if any task failed 27 | scope.join(); 28 | 29 | // Retrieve results using get() after join() succeeds 30 | IO.println(task1.get()); 31 | IO.println(task2.get()); 32 | IO.println(task3.get()); 33 | 34 | } catch (StructuredTaskScope.FailedException e) { 35 | IO.println("One or more tasks failed: " + e.getCause()); 36 | } catch (InterruptedException e) { 37 | IO.println("Interrupted while waiting for tasks."); 38 | } 39 | } 40 | 41 | private static String work(String name, int delayMillis) throws Exception { 42 | Thread.sleep(delayMillis); 43 | if (name.contains("fails")) { 44 | throw new RuntimeException(name + " encountered an error!"); 45 | } 46 | return name + " completed successfully"; 47 | } 48 | -------------------------------------------------------------------------------- /09-threads/snippets/src/howmany/HowManyVirtualThreadsDoingSomething.java: -------------------------------------------------------------------------------- 1 | package howmany; 2 | 3 | import java.time.Duration; 4 | import java.util.concurrent.atomic.AtomicLong; 5 | 6 | import static howmany.HowManyThreadsHelper.doSomething; 7 | 8 | public class HowManyVirtualThreadsDoingSomething { 9 | 10 | // Activate basic GC logging: -Xlog:gc 11 | 12 | // jmap -histo 13 | // Produces a class histogram (counts and total bytes per class) from the Java heap. 14 | // Light‑weight, quick, great for spotting which classes dominate heap usage. 15 | 16 | private static final int NUMBER_OF_VIRTUAL_THREADS = 1_000_000_000; 17 | private static final int PRINT_STEP = Math.min(NUMBER_OF_VIRTUAL_THREADS / 10, 100_000); 18 | 19 | public static void main(String[] args) throws InterruptedException { 20 | AtomicLong runningThreadsCounter = new AtomicLong(); 21 | 22 | long startTime = System.currentTimeMillis(); 23 | 24 | for (int i = 1; i <= NUMBER_OF_VIRTUAL_THREADS; i++) { 25 | Thread.ofVirtual() 26 | .start( 27 | () -> { 28 | runningThreadsCounter.incrementAndGet(); 29 | doSomething(); 30 | }); 31 | 32 | if (i % PRINT_STEP == 0) { 33 | long runningThreads = runningThreadsCounter.get(); 34 | long time = System.currentTimeMillis() - startTime; 35 | System.out.printf( 36 | "%,d virtual threads started, %,d virtual threads running after %,d ms%n", 37 | i, runningThreads, time); 38 | 39 | if (i - runningThreads > 200_000) { 40 | HowManyThreadsHelper.waitForVirtualThreadsToCatchUp(i, runningThreadsCounter, startTime); 41 | } 42 | } 43 | } 44 | 45 | HowManyThreadsHelper.waitForVirtualThreadsToCatchUp( 46 | NUMBER_OF_VIRTUAL_THREADS, runningThreadsCounter, startTime); 47 | 48 | // Sleep, so we can look at the memory usage 49 | Thread.sleep(Duration.ofHours(1)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/snippets/test/bg/sofia/uni/fmi/mjt/math/NumberUtilsTest.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.math; 2 | 3 | import org.junit.jupiter.api.MethodOrderer; 4 | import org.junit.jupiter.api.Order; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.TestMethodOrder; 7 | 8 | import static org.junit.jupiter.api.Assertions.assertFalse; 9 | import static org.junit.jupiter.api.Assertions.assertThrows; 10 | import static org.junit.jupiter.api.Assertions.assertTrue; 11 | 12 | @TestMethodOrder(MethodOrderer.Default.OrderAnnotation.class) 13 | // toggle commented line to change the explicit test method execution order 14 | // @TestMethodOrder(MethodOrderer.MethodName.class) 15 | class NumberUtilsTest { 16 | 17 | @Test 18 | @Order(1) 19 | void testIsPrimeNegativeArgument() { 20 | assertThrows(IllegalArgumentException.class, () -> NumberUtils.isPrime(-16), 21 | "Negative numbers are not a legal argument"); 22 | } 23 | 24 | @Test 25 | @Order(2) 26 | void testIsPrimeZero() { 27 | assertThrows(IllegalArgumentException.class, () -> NumberUtils.isPrime(0), "Zero is not a legal argument"); 28 | } 29 | 30 | @Test 31 | @Order(3) 32 | void testIsPrimeOne() { 33 | assertThrows(IllegalArgumentException.class, () -> NumberUtils.isPrime(1), "One is not a legal argument"); 34 | } 35 | 36 | @Test 37 | @Order(4) 38 | void testIsPrimeTwo() { 39 | assertTrue(NumberUtils.isPrime(2), "Two is prime"); 40 | } 41 | 42 | @Test 43 | @Order(5) 44 | void testIsPrimeFour() { 45 | assertFalse(NumberUtils.isPrime(4), "Four is not prime"); 46 | } 47 | 48 | @Test 49 | @Order(6) 50 | void testIsPrimeNine() { 51 | assertFalse(NumberUtils.isPrime(9), "Nine is not prime"); 52 | } 53 | 54 | @Test 55 | @Order(7) 56 | void testIsPrimeEleven() { 57 | assertTrue(NumberUtils.isPrime(11), "Eleven is prime"); 58 | } 59 | 60 | @Test 61 | @Order(8) 62 | void testIsPrimeTwelve() { 63 | assertFalse(NumberUtils.isPrime(12), "Twelve is not prime"); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /playground/02-dna-analyzer/README.md: -------------------------------------------------------------------------------- 1 | ### Анализ на ДНК :microscope: 2 | 3 | Задачата е вдъхновена от курс по алгоритми във [Факултета по Компютърни науки](https://www.cs.princeton.edu) на [Princeton University](https://www.princeton.edu). 4 | 5 | ### Условие 6 | 7 | Ще имплементираме детектор, определящ най-дългата повтаряща се последователност от символи в даден (потенциално много дълъг) низ. Например, "abra" е най-дългата повтаряща се последователност в низа "abracadabra". Ако има две или повече повтарящи се последователности с еднаква дължина, детекторът връща произволна от тях. 8 | 9 | За да вкараме малко контекст и перспектива, тази на пръв поглед самоцелна задача е възникнала покрай реални проблеми в областта на обработката на текстове на естествен език и криптографията, а днес тя има революционни приложения в молекулярната биология. В ДНК-то, разглеждано като последователност от нуклеобази (аденин, тимин, гуанин, цитозин), има забележително количество повтарящи се последователности, и те играят критична роля в различни биологични функции, както и в еволюцията на видовете. 10 | 11 | **Забележка** 12 | *Brute force* решението е сравнително просто, но е с алгоритмична сложност O(N^3). Ако се справите и искате да задълбаете в посока алгоритми, хубаво предизвикателство е да се опитате да решите задачата с по-бърз алгоритъм. Търсенето на ефективни алгоритми за намиране на повтарящи се последователности в символни редици (*redundancy detection problem*) днес е област на активни изследвания, защото подобни алгоритми ще позволят на учените да разгадаят някои от големите загадки в молекулярната биология. 13 | 14 | Създайте публичен клас `DNAAnalyzer` с метод 15 | 16 | ```java 17 | public static String longestRepeatingSequence(String dna) 18 | ``` 19 | 20 | който приема низ като параметър и връща (пак като низ) най-дългата повтаряща се последователност от символи в низа. 21 | 22 | ### Примери 23 | 24 | | Извикване | Резултат | 25 | |:-------------------------------------------- |:--------- | 26 | | `longestRepeatingSequence("abracadabra")` | `"abra"` | 27 | | `longestRepeatingSequence("ATACTCGGTACTCT")` | `"TACTC"` | 28 | -------------------------------------------------------------------------------- /10-network/snippets/src/threadpools/ScheduledThreadPoolExample.java: -------------------------------------------------------------------------------- 1 | package threadpools; 2 | 3 | import java.util.concurrent.Executors; 4 | import java.util.concurrent.ScheduledExecutorService; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | public class ScheduledThreadPoolExample { 8 | 9 | // A scheduled thread pool is used for scheduling tasks 10 | // to execute after a delay or to execute periodically. 11 | 12 | static void main() throws InterruptedException { 13 | 14 | // Creates a scheduled thread pool with 2 threads. 15 | ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10); 16 | 17 | // Schedule tasks 18 | scheduler.schedule(() -> System.out.println("Delayed task executed after 5 seconds"), 5, TimeUnit.SECONDS); 19 | 20 | // Schedule a task to repeat at a fixed rate. 21 | // The interval is based on the scheduled start time of each execution, maintaining a strict execution schedule 22 | // which may lead to task overlap if execution time exceeds the scheduled rate. 23 | scheduler.scheduleAtFixedRate(() -> { 24 | doSomeWork(2_000); 25 | System.out.println("Some regular task executed at fixed rate by " + Thread.currentThread().getName()); 26 | }, 0, 1, TimeUnit.SECONDS); 27 | 28 | // Schedule a task to repeat with a fixed delay based on the actual completion time of the previous execution, 29 | // providing buffer time if the task takes longer, preventing task overlap. 30 | scheduler.scheduleWithFixedDelay(() -> { 31 | doSomeWork(2_000); 32 | System.out.println("Some regular task executed with fixed delay by " + Thread.currentThread().getName()); 33 | }, 0, 1, TimeUnit.SECONDS); 34 | 35 | // Shut down the scheduler after some delay to allow time for tasks to execute. 36 | scheduler.schedule(() -> scheduler.shutdown(), 20, TimeUnit.SECONDS); 37 | 38 | } 39 | 40 | private static void doSomeWork(long millis) { 41 | try { 42 | Thread.sleep(millis); 43 | } catch (InterruptedException e) { 44 | throw new RuntimeException(e); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /07-io-streams-and-files/snippets/src/bg/sofia/uni/fmi/mjt/io/ObjectStreamExample.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.io; 2 | 3 | import java.io.EOFException; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.io.ObjectInputStream; 7 | import java.io.ObjectOutputStream; 8 | import java.io.UncheckedIOException; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | 12 | public class ObjectStreamExample { 13 | 14 | static void main() { 15 | Path filePath = Path.of("students.bin"); 16 | Student firstStudent = new Student("Gosho", 20); 17 | Student secondStudent = new Student("Stamat", 80); 18 | 19 | //writeStudentsToFile(filePath, firstStudent, secondStudent); 20 | readStudentsFromFile(filePath); 21 | } 22 | 23 | private static void writeStudentsToFile(Path file, Student... students) { 24 | try (var objectOutputStream = new ObjectOutputStream(Files.newOutputStream(file))) { 25 | for (Student student : students) { 26 | objectOutputStream.writeObject(student); 27 | objectOutputStream.flush(); 28 | } 29 | } catch (IOException e) { 30 | throw new UncheckedIOException("A problem occurred while writing to a file", e); 31 | } 32 | } 33 | 34 | private static void readStudentsFromFile(Path file) { 35 | try (var objectInputStream = new ObjectInputStream(Files.newInputStream(file))) { 36 | 37 | Object studentObject; 38 | while ((studentObject = objectInputStream.readObject()) != null) { 39 | System.out.println(studentObject); 40 | 41 | Student s = (Student) studentObject; 42 | System.out.println("Name " + s.getName()); 43 | } 44 | 45 | } catch (EOFException e) { 46 | // EMPTY BODY 47 | } catch (FileNotFoundException e) { 48 | throw new UncheckedIOException("The files does not exist", e); 49 | } catch (IOException e) { 50 | throw new UncheckedIOException("A problem occurred while reading from a file", e); 51 | } catch (ClassNotFoundException e) { 52 | throw new RuntimeException(e); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /09-threads/snippets/src/howmany/HowManyVirtualThreads.java: -------------------------------------------------------------------------------- 1 | package howmany; 2 | 3 | import java.time.Duration; 4 | import java.util.concurrent.atomic.AtomicLong; 5 | 6 | public class HowManyVirtualThreads { 7 | 8 | // Activate basic GC logging: -Xlog:gc 9 | 10 | // jmap -histo 11 | // Produces a class histogram (counts and total bytes per class) from the Java heap. 12 | // Light‑weight, quick, great for spotting which classes dominate heap usage. 13 | 14 | private static final int NUMBER_OF_VIRTUAL_THREADS = 100_000_000; 15 | private static final int PRINT_STEP = Math.min(NUMBER_OF_VIRTUAL_THREADS / 10, 100_000); 16 | 17 | static void main() throws InterruptedException { 18 | AtomicLong runningThreadsCounter = new AtomicLong(); 19 | 20 | long startTime = System.currentTimeMillis(); 21 | 22 | for (int i = 1; i <= NUMBER_OF_VIRTUAL_THREADS; i++) { 23 | Thread.ofVirtual() 24 | .start( 25 | () -> { 26 | runningThreadsCounter.incrementAndGet(); 27 | try { 28 | Thread.sleep(Duration.ofDays(100)); 29 | } catch (InterruptedException e) { 30 | // Let the thread die 31 | } 32 | System.out.println("I died"); 33 | }); 34 | 35 | if (i % PRINT_STEP == 0) { 36 | long runningThreads = runningThreadsCounter.get(); 37 | long time = System.currentTimeMillis() - startTime; 38 | System.out.printf( 39 | "%,d virtual threads started, %,d virtual threads running after %,d ms%n", 40 | i, runningThreads, time); 41 | 42 | if (i - runningThreads > 100_000) { 43 | HowManyThreadsHelper.waitForVirtualThreadsToCatchUp(i, runningThreadsCounter, startTime); 44 | } 45 | } 46 | } 47 | 48 | HowManyThreadsHelper.waitForVirtualThreadsToCatchUp( 49 | NUMBER_OF_VIRTUAL_THREADS, runningThreadsCounter, startTime); 50 | 51 | // Sleep, so we can look at the memory usage 52 | Thread.sleep(Duration.ofHours(1)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/codesize.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | The Code Size Ruleset contains a collection of rules that find 9 | code size related problems. This version of the ruleset includes 10 | alternate messages from the main PMD rulesets/java/codesize.xml ruleset. 11 | 12 | 13 | 17 | 18 | 24 | 25 | 31 | 32 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/strictexception.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | These rules provide some strict guidelines about throwing and 9 | catching exceptions. This version of the ruleset includes 10 | alternate messages from the main PMD rulesets/java/strictexception.xml 11 | ruleset. 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 35 | 36 | 38 | 39 | 42 | 43 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/unnecessary.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | The Unnecessary Code Ruleset contains rules that find unnecessary. 9 | This version of the ruleset includes alternate messages from the main PMD 10 | rulesets/java/unnecessary.xml ruleset. 11 | 12 | 13 | 17 | 18 | 21 | 22 | 26 | 27 | 32 | 33 | 37 | 38 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /06-unit-testing-and-mocking/lab/resources/src/bg/sofia/uni/fmi/mjt/pipeline/Cache.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.pipeline; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * A simple generic cache for storing key-value pairs in memory. 7 | *

8 | * This class is used internally by {@link Pipeline} to cache results of previous 9 | * executions and avoid re-computation for the same input. The keys and values 10 | * are stored as {@code Object}, so type safety is not enforced at compile time. 11 | * Be careful when retrieving cached values to cast them to the correct type. 12 | */ 13 | public class Cache { 14 | 15 | private final Map cache; 16 | 17 | /** 18 | * Creates a new, empty cache. 19 | */ 20 | public Cache() {this.cache = new HashMap<>();} 21 | 22 | /** 23 | * Stores a value associated with the given key. 24 | * If the key already exists, the previous value is overwritten. 25 | * 26 | * @param key the key to store 27 | * @param value the value associated with the key 28 | * 29 | * @throws IllegalArgumentException if key or value is null 30 | */ 31 | public void cacheValue(Object key, Object value) { 32 | cache.put(key, value); 33 | } 34 | 35 | /** 36 | * Retrieves the cached value for the given key. 37 | * 38 | * @param key the key whose value is to be returned 39 | * @return the cached value, or {@code null} if the key is not present 40 | * 41 | * @throws IllegalArgumentException if key is null 42 | */ 43 | public Object getCachedValue(Object key) { 44 | return cache.get(key); 45 | } 46 | 47 | /** 48 | * Checks if a value is cached for the given key. 49 | * 50 | * @param key the key to check 51 | * @return {@code true} if the cache contains the key, {@code false} otherwise 52 | * 53 | * @throws IllegalArgumentException if key is null 54 | */ 55 | public boolean containsKey(Object key) { 56 | return cache.containsKey(key); 57 | } 58 | 59 | /** 60 | * Clears all entries from the cache. 61 | */ 62 | public void clear() { 63 | cache.clear(); 64 | } 65 | 66 | /** 67 | * Checks if the cache is empty 68 | * */ 69 | public boolean isEmpty() { 70 | return cache.isEmpty(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /09-threads/snippets/src/WaitNotifyExample.java: -------------------------------------------------------------------------------- 1 | public class WaitNotifyExample { 2 | 3 | static void main() throws Exception { 4 | CreditBankAccount account = new CreditBankAccount("Student"); 5 | 6 | // The thread will try to withdraw 100 7 | CreditFeeTaker creditFeeTaker = new CreditFeeTaker(account, 100); 8 | creditFeeTaker.start(); 9 | 10 | // The thread will try to withdraw 50 11 | CreditFeeTaker creditFeeTaker2 = new CreditFeeTaker(account, 50); 12 | creditFeeTaker2.start(); 13 | 14 | // Wait a bit 15 | Thread.sleep(500); 16 | 17 | // Deposit 120 18 | account.deposit(120); 19 | 20 | // Wait a bit 21 | Thread.sleep(500); 22 | 23 | // Deposit more money 24 | account.deposit(30); 25 | 26 | creditFeeTaker.join(); 27 | creditFeeTaker2.join(); 28 | System.out.println(account); 29 | } 30 | } 31 | 32 | class CreditBankAccount extends BankAccount { 33 | public CreditBankAccount(String name) { 34 | super(name, 0); 35 | } 36 | 37 | @Override 38 | public synchronized void deposit(double amount) { 39 | super.deposit(amount); 40 | // We use notifyAll() as there may be enough money so few threads can proceed. 41 | this.notifyAll(); 42 | } 43 | 44 | public synchronized void withdrawCreditPayment(double monthFee) { 45 | // Guarded wait - we check in while block whether the condition is met 46 | // if not - the thread will wait again. This enables us to safely use notifyAll 47 | while (balance < monthFee) { 48 | System.out.println("Not enough money, thread will wait"); 49 | try { 50 | this.wait(); 51 | } catch (InterruptedException e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | 56 | withdraw(monthFee); 57 | System.out.println("Successfully withdrew money. Remaining balance " + balance); 58 | } 59 | } 60 | 61 | class CreditFeeTaker extends Thread { 62 | private CreditBankAccount account; 63 | private double fee; 64 | 65 | public CreditFeeTaker(CreditBankAccount account, double fee) { 66 | this.account = account; 67 | this.fee = fee; 68 | } 69 | 70 | @Override 71 | public void run() { 72 | account.withdrawCreditPayment(this.fee); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /playground/03-dungeons/SampleDungeonsTest.java: -------------------------------------------------------------------------------- 1 | package bg.sofia.uni.fmi.mjt.dungeon; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertFalse; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import bg.sofia.uni.fmi.mjt.dungeon.actor.Enemy; 10 | import bg.sofia.uni.fmi.mjt.dungeon.actor.Hero; 11 | import bg.sofia.uni.fmi.mjt.dungeon.treasure.Spell; 12 | import bg.sofia.uni.fmi.mjt.dungeon.treasure.Treasure; 13 | import bg.sofia.uni.fmi.mjt.dungeon.treasure.Weapon; 14 | 15 | public class GameEngineTest { 16 | private Hero hero; 17 | private char[][] map; 18 | private Enemy[] enemies; 19 | private Treasure[] treasures; 20 | private GameEngine gameEngine; 21 | 22 | @Before 23 | public void setup() { 24 | hero = new Hero("hero", 100, 100); 25 | map = new char[][]{ "###".toCharArray(), 26 | "TS.".toCharArray(), 27 | "#EG".toCharArray() }; 28 | enemies = new Enemy[] {new Enemy("enemy", 100, 0, new Weapon("enemy weapon", 30), null)}; 29 | treasures = new Treasure[] {new Weapon("strong weapon", 50)}; 30 | gameEngine = new GameEngine(map, hero, enemies, treasures); 31 | } 32 | 33 | @Test 34 | public void testMoveToEmptyBlock() { 35 | String moveMessage = gameEngine.makeMove(Direction.RIGHT); 36 | 37 | assertEquals("You moved successfully to the next position.", moveMessage); 38 | assertEquals('.', gameEngine.getMap()[1][1]); 39 | assertEquals('H', gameEngine.getMap()[1][2]); 40 | } 41 | 42 | @Test 43 | public void testMoveToObstacle() { 44 | gameEngine.makeMove(Direction.RIGHT); 45 | String moveMessage = gameEngine.makeMove(Direction.UP); 46 | 47 | assertEquals("Wrong move. There is an obstacle and you cannot bypass it.", moveMessage); 48 | assertEquals('H', gameEngine.getMap()[1][2]); 49 | } 50 | 51 | @Test 52 | public void testMoveToTreasure() { 53 | String moveMessage = gameEngine.makeMove(Direction.LEFT); 54 | 55 | assertEquals("Weapon found! Damage points: 50", moveMessage); 56 | assertEquals('.', gameEngine.getMap()[1][1]); 57 | assertEquals('H', gameEngine.getMap()[1][0]); 58 | 59 | assertEquals("strong weapon", gameEngine.getHero().getWeapon().getName()); 60 | assertEquals(50, gameEngine.getHero().getWeapon().getDamage()); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /09-threads/snippets/src/NonTrivialDeadLock.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Complex dead-lock example. 3 | */ 4 | public class NonTrivialDeadLock { 5 | 6 | static void main() throws Exception { 7 | BankAccount ivan = new BankAccount("Ivan", 1_000); 8 | BankAccount pesho = new BankAccount("Pesho", 1_000); 9 | 10 | Thread t1 = new Thread(() -> transferNaive(ivan, pesho, 100)); 11 | 12 | Thread t2 = new Thread(() -> transferNaive(pesho, ivan, 100)); 13 | 14 | t1.start(); 15 | t2.start(); 16 | t1.join(); 17 | t2.join(); 18 | 19 | System.out.println(ivan); 20 | System.out.println(pesho); 21 | } 22 | 23 | // This will deadlock! 24 | public static void transferNaive(BankAccount source, BankAccount target, double amount) { 25 | synchronized (source) { 26 | System.out.println("Locked " + source.hashCode()); 27 | 28 | try { 29 | Thread.sleep(500); 30 | } catch (InterruptedException e) { 31 | e.printStackTrace(); 32 | } 33 | 34 | synchronized (target) { 35 | System.out.println("Locked " + target.hashCode()); 36 | 37 | source.withdraw(amount); 38 | target.deposit(amount); 39 | } 40 | } 41 | } 42 | 43 | public static void transfer(BankAccount source, BankAccount target, double amount) { 44 | BankAccount first; 45 | BankAccount second; 46 | 47 | // Always order the locks in the same way 48 | // Here, we will use the names of the accounts' owners 49 | // The names are immutable so we can use them safely outside synchronized block 50 | if (source.getName().compareTo(target.getName()) < 0) { 51 | first = source; 52 | second = target; 53 | } else { 54 | first = target; 55 | second = source; 56 | } 57 | 58 | synchronized (first) { 59 | System.out.println("Locked " + first.hashCode()); 60 | 61 | try { 62 | Thread.sleep(500); 63 | } catch (InterruptedException e) { 64 | e.printStackTrace(); 65 | } 66 | synchronized (second) { 67 | System.out.println("Locked " + second.hashCode()); 68 | 69 | source.withdraw(amount); 70 | target.deposit(amount); 71 | } 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/junit.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | These rules deal with different problems that can occur with JUnit 9 | tests. This version of the ruleset includes alternate messages 10 | from the main PMD rulesets/java/design.xml ruleset. 11 | 12 | 13 | 14 | 17 | 18 | 22 | 24 | 26 | 28 | 29 | 30 | 37 | 40 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /10-network/snippets/src/threadsafecollections/ConcurrentVsSynchronizedMap.java: -------------------------------------------------------------------------------- 1 | package threadsafecollections; 2 | 3 | import java.util.Hashtable; 4 | import java.util.Map; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | 7 | public class ConcurrentVsSynchronizedMap { 8 | 9 | private static final int NUM_THREADS = 2_000; 10 | private static final int NUM_OPERATIONS = 10_000; 11 | 12 | public static void main() throws InterruptedException { 13 | 14 | // Hashtable example 15 | Map hashtable = new Hashtable<>(); 16 | 17 | long hashtableStartTime = System.nanoTime(); 18 | Thread[] hashtableThreads = new Thread[NUM_THREADS]; 19 | 20 | for (int i = 0; i < NUM_THREADS; i++) { 21 | hashtableThreads[i] = new Thread(() -> { 22 | for (int j = 0; j < NUM_OPERATIONS; j++) { 23 | hashtable.put(j, j); 24 | hashtable.get(j); 25 | } 26 | }); 27 | } 28 | 29 | for (int i = 0; i < NUM_THREADS; i++) { 30 | hashtableThreads[i].start(); 31 | } 32 | for (int i = 0; i < NUM_THREADS; i++) { 33 | hashtableThreads[i].join(); 34 | } 35 | 36 | long hashtableEndTime = System.nanoTime(); 37 | 38 | System.out.println("Hashtable execution time: " + (hashtableEndTime - hashtableStartTime) / 1_000_000 + " ms"); 39 | 40 | // ConcurrentHashMap example 41 | Map concurrentHashMap = new ConcurrentHashMap<>(); 42 | 43 | long concurrentHashMapStartTime = System.nanoTime(); 44 | Thread[] concurrentHashMapThreads = new Thread[NUM_THREADS]; 45 | 46 | for (int i = 0; i < NUM_THREADS; i++) { 47 | concurrentHashMapThreads[i] = new Thread(() -> { 48 | for (int j = 0; j < NUM_OPERATIONS; j++) { 49 | concurrentHashMap.put(j, j); 50 | concurrentHashMap.get(j); 51 | } 52 | }); 53 | } 54 | 55 | for (int i = 0; i < NUM_THREADS; i++) { 56 | concurrentHashMapThreads[i].start(); 57 | } 58 | for (int i = 0; i < NUM_THREADS; i++) { 59 | concurrentHashMapThreads[i].join(); 60 | } 61 | 62 | long concurrentHashMapEndTime = System.nanoTime(); 63 | 64 | System.out.println( 65 | "ConcurrentHashMap execution time: " + (concurrentHashMapEndTime - concurrentHashMapStartTime) / 1_000_000 + 66 | " ms"); 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /playground/04-cryptic-letter/README.md: -------------------------------------------------------------------------------- 1 | ## Загадъчно писмо :secret: 2 | 3 | Това мистериозно послание в код пристигна по пощата една сутрин. Разбираш ли нещо? 4 | 5 | ```java 6 | public class LetterDecoder { 7 | 8 | /** 9 | * Ava J. sent you a letter for your secret annual meeting. 10 | * You must decode it to understand when the meeting will take place. 11 | * Ava never makes mistakes when writing her letters. If you ever see one, consider that a clue. 12 | *

13 | * The first 3 letters of Ava's letters always represents the *month*. Be sure of that. 14 | *

15 | * Decode the exact *hour* of the meeting by counting the number of hidden paragraphs. 16 | * If you see a punctuation mistake that would mean the end of a hidden paragraph. *1* 17 | * If you count more that 24 hours, something is not quite right. 18 | *

19 | * Decode the exact *minutes* of the meeting by counting the number of misplaced symbols. 20 | * For every misplaced symbol add 5 minutes. *2* 21 | * If you count more than 60 minutes, something is not quite right. 22 | *

23 | * Decode the exact *day* of the month Ava wants you to meet her by counting the length 24 | * of the hidden paragraph which starts with the word "The" (including a period at the end). *3,4* 25 | *

26 | * *1* - Ava would never make punctuation mistakes. 27 | * Normally every sentence in her letters ends with one occurrence of a period, no more no less. 28 | * *2* - Ava would never replace letters from the alphabet with symbols. 29 | * Normally she writes S instead of $. 30 | * *3* - Ava would never start a hidden paragraph with the word "The". 31 | * *4* - Ava would never leave a lot of unnecessary space between the hidden paragraphs. 32 | * Either at the start, or the end. 33 | * 34 | * @param message The coded message that Ava sent you. 35 | * @return decoded Message in the format [*day* *month* at *hour*:*minutes*], e.g. "17th October at 9:00". 36 | * Print "Maybe another *time*" if you feel something is not right. 37 | * (Replace *time* with the reason you think the meeting might not happen, 38 | * е.g. "Maybe another day" or "Maybe another minute"). 39 | * If the message is empty, print "Maybe another day". 40 | */ 41 | public String decodeMessage(final String message) { 42 | // TBD: replace with your solution 43 | return null; 44 | } 45 | 46 | } 47 | ``` 48 | 49 | Напомня ми за една случка от *A Series of Unfortunate Events*. 50 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | The JavaTddPlugin PMD Rules ruleset contains the full collection of 8 | checks we expect all of our students to follow at Virginia Tech. It 9 | also serves as the default PMD ruleset for Web-CAT users using the 10 | JavaTddPlugin for automated grading. This ruleset contains a subset 11 | of the checks in all of the sets predefined in PMD 3.8, together with 12 | a couple of custom checks. Grant Braught at Dickinson College has 13 | also contributed a number of customized error messages for various 14 | rules. 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /04-collections-clean-code/snippets/src/comparators/Main.java: -------------------------------------------------------------------------------- 1 | package comparators; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.TreeMap; 9 | 10 | public class Main { 11 | 12 | public static void main(String... args) { 13 | 14 | Car first = new Car("1G1RB5F49KP123456", 200, "red", "Ferrari"); 15 | Car second = new Car("JN1AZ42MX987654", 100, "green", "Mercedes"); 16 | Car third = new Car("2HKM28NG543210", 50, "blue", "BMW"); 17 | Car fourth = new Car("WBA345F83PT567890", 150, "black", "Audi"); 18 | 19 | List cars = new ArrayList<>(); 20 | 21 | cars.add(first); 22 | cars.add(second); 23 | cars.add(third); 24 | cars.add(fourth); 25 | 26 | Collections.sort(cars); 27 | System.out.println("Sorting the cars according to their natural order: by topSpeed, ascending:"); 28 | for (Car car : cars) { 29 | System.out.println(car); 30 | } 31 | 32 | Collections.sort(cars, new CarByBrandComparator()); 33 | System.out.println("\nCustom sorting the cars by brand name lexicographically:"); 34 | for (Car car : cars) { 35 | System.out.println(car); 36 | } 37 | 38 | Collections.sort(cars, new CarByTopSpeedDescComparator()); 39 | System.out.println("\nCustom sorting the cars by topSpeed in descending order:"); 40 | for (Car car : cars) { 41 | System.out.println(car); 42 | } 43 | 44 | // Map 45 | Map carStorage = new HashMap<>(); 46 | carStorage.put(first, 3); 47 | carStorage.put(second, 4); 48 | carStorage.put(third, 10); 49 | carStorage.put(fourth, 25); 50 | 51 | System.out.println("\nIterating the carStorage hash map:"); 52 | for (Map.Entry entry : carStorage.entrySet()) { 53 | System.out.println(entry.getKey() + " " + entry.getValue()); 54 | } 55 | 56 | System.out.println("\nSorting the cars storage map by the key's natural order: topSpeed, ascending:"); 57 | Map sortedStorage = new TreeMap<>(); 58 | sortedStorage.putAll(carStorage); 59 | for (Map.Entry entry : sortedStorage.entrySet()) { 60 | System.out.println(entry.getKey() + " " + entry.getValue()); 61 | } 62 | 63 | System.out.println("\nCustom sorting the cars storage map by the key's by brand name lexicographically:"); 64 | Map sortedStorageCustom = new TreeMap<>(new CarByBrandComparator()); 65 | sortedStorageCustom.putAll(carStorage); 66 | for (Map.Entry entry : sortedStorageCustom.entrySet()) { 67 | System.out.println(entry.getKey() + " " + entry.getValue()); 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /docs/02-code-analysis-tools/PMD/pmd-rulesets/naming.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | The Naming Ruleset contains a collection of rules about names - 9 | too long, too short, and so forth. This version of the ruleset 10 | includes alternate messages from the main PMD rulesets/java/naming.xml 11 | ruleset. 12 | 13 | 14 | 15 | 16 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 50 | 51 | 52 | 53 | 54 | 55 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /09-threads/snippets/src/RaceSimulation.java: -------------------------------------------------------------------------------- 1 | class FinishLine { 2 | 3 | // what will happen if this method is not synchronized? 4 | public synchronized void cross(String runner) { 5 | String GREEN = "\u001B[32m"; 6 | String RESET = "\u001B[0m"; 7 | System.out.println(GREEN + runner + " has reached the finish line and takes a photo!" + RESET); 8 | try { 9 | // time to take a photo ;) 10 | Thread.sleep(1_000); 11 | } catch (InterruptedException e) { 12 | Thread.currentThread().interrupt(); 13 | } 14 | String RED = "\u001B[31m"; 15 | System.out.println(RED + runner + " crossed the finish line!" + RESET); 16 | } 17 | } 18 | 19 | class Runner extends Thread { 20 | private final String name; 21 | private final FinishLine finishLine; 22 | 23 | public Runner(String name, FinishLine finishLine) { 24 | this.name = name; 25 | this.finishLine = finishLine; 26 | } 27 | 28 | public void run() { 29 | System.out.println(name + " started running!"); 30 | try { 31 | // random running speed for each competitor 32 | Thread.sleep((long) (Math.random() * 3000)); 33 | } catch (InterruptedException e) { 34 | Thread.currentThread().interrupt(); 35 | } 36 | midRace(); 37 | finishLine.cross(name); 38 | } 39 | 40 | // not synchronized 41 | public void midRace() { 42 | System.out.println(name + " has completed half of the distance!"); 43 | try { 44 | // some may run out of energy ;( 45 | Thread.sleep((long) (Math.random() * 3_000)); 46 | } catch (InterruptedException e) { 47 | Thread.currentThread().interrupt(); 48 | } 49 | System.out.println(name + " stop to drink water!"); 50 | } 51 | } 52 | 53 | public class RaceSimulation { 54 | static void main() { 55 | FinishLine finishLine = new FinishLine(); 56 | 57 | Runner runner1 = new Runner("Victor", finishLine); 58 | Runner runner2 = new Runner("Ismo", finishLine); 59 | Runner runner3 = new Runner("100yo", finishLine); 60 | 61 | runner1.start(); 62 | runner2.start(); 63 | runner3.start(); 64 | 65 | try { 66 | Thread.sleep(1_000); 67 | } catch (InterruptedException e) { 68 | Thread.currentThread().interrupt(); 69 | } 70 | String BLUE = "\u001B[34m"; 71 | String RESET = "\u001B[0m"; 72 | System.out.println(BLUE + "The main thread continues with his work while the runners race" + RESET); 73 | 74 | try { 75 | runner1.join(); 76 | runner2.join(); 77 | runner3.join(); 78 | } catch (InterruptedException e) { 79 | Thread.currentThread().interrupt(); 80 | } 81 | 82 | System.out.println("All runners have finished the race."); 83 | } 84 | } 85 | --------------------------------------------------------------------------------